001: /*
002: * @(#)RandomAccessROMFile.java 1.14 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package sun.io;
029:
030: import java.io.*;
031:
032: /**
033: * Instances of this class support reading of files in ROM.
034: *
035: * WARNING: This is not production code and is only meant as an example of
036: * how to access files romized by JavaDataCompact. Among other things, no attempt
037: * is made to syncronize any of the calls. This can result in errors when
038: * two threads are trying to access the same file through the same
039: * RandomAccessROMFile instance, or if 2 threads are trying
040: * to open a romfile at the same time, even if each is opening a different
041: * romfile.
042: *
043: */
044: public class RandomAccessROMFile extends InputStream implements
045: DataInput {
046: private FileDescriptor fd;
047:
048: /**
049: * Creates a random access file stream to read from with the specified name.
050: * <p>
051: * The mode argument must either be equal to <code>"r"</code>.
052: *
053: * @param name the system-dependent filename.
054: * @param mode the access mode.
055: * @exception IllegalArgumentException if the mode argument is not equal
056: * to <code>"r"</code>.
057: * @exception IOException if an I/O error occurs.
058: * @exception SecurityException if a security manager exists, its
059: * <code>checkRead</code> method is called with the name
060: * argument to see if the application is allowed read access
061: * to the file. this may result in a security exception.
062: * @see java.lang.SecurityException
063: * @see java.lang.SecurityManager#checkRead(java.lang.String)
064: */
065: public RandomAccessROMFile(String name, String mode)
066: throws IOException {
067: if (!mode.equals("r"))
068: throw new IllegalArgumentException("mode must be r");
069: SecurityManager security = System.getSecurityManager();
070: if (security != null)
071: security.checkRead(name);
072: fd = new FileDescriptor();
073: open(name);
074: }
075:
076: /**
077: * Creates a random access file stream to read from.
078: * <p>
079: * The mode argument must either be equal to <code>"r"</code>.
080: *
081: * @param file the file object.
082: * @param mode the access mode.
083: * @exception IllegalArgumentException if the mode argument is not equal
084: * to <code>"r"</code>.
085: * @exception IOException if an I/O error occurs.
086: * @exception SecurityException if a security manager exists, its
087: * <code>checkRead</code> method is called with the pathname
088: * of the <code>File</code> argument to see if the
089: * application is allowed read access to the file.
090: * @see java.io.File#getPath()
091: * @see java.lang.SecurityManager#checkRead(java.lang.String)
092: */
093: public RandomAccessROMFile(FileIO file, String mode)
094: throws IOException {
095: this (file.getPath(), mode);
096: }
097:
098: /**
099: * Returns the opaque file descriptor object associated with this stream.
100: *
101: * @return the file descriptor object associated with this stream.
102: * @exception IOException if an I/O error occurs.
103: * @see java.io.FileDescriptor
104: * @since JDK1.0
105: */
106: public final FileDescriptor getFD() throws IOException {
107: if (fd != null)
108: return fd;
109: throw new IOException();
110: }
111:
112: /**
113: * Opens a file and returns the file descriptor. The file is
114: * opened as read-only.
115: * @param name the name of the file
116: */
117: private native void open(String name) throws IOException;
118:
119: // 'Read' primitives
120:
121: /**
122: * Reads a byte of data from this file. This method blocks if no
123: * input is yet available.
124: *
125: * @return the next byte of data, or <code>-1</code> if the end of the
126: * file is reached.
127: * @exception IOException if an I/O error occurs.
128: * @since JDK1.0
129: */
130: public native int read() throws IOException;
131:
132: /**
133: * Reads a sub array as a sequence of bytes.
134: * @param b the buffer where data is to be written
135: * @param off the start offset in the data
136: * @param len the number of bytes that are to be read
137: * @exception IOException If an I/O error has occurred.
138: */
139: private native int readBytes(byte b[], int off, int len)
140: throws IOException;
141:
142: /**
143: * Reads up to <code>len</code> bytes of data from this file into an
144: * array of bytes. This method blocks until at least one byte of input
145: * is available.
146: *
147: * @param b the buffer into which the data is read.
148: * @param off the start offset of the data.
149: * @param len the maximum number of bytes read.
150: * @return the total number of bytes read into the buffer, or
151: * <code>-1</code> if there is no more data because the end of
152: * the file has been reached.
153: * @exception IOException if an I/O error occurs.
154: * @since JDK1.0
155: */
156: public int read(byte b[], int off, int len) throws IOException {
157: return readBytes(b, off, len);
158: }
159:
160: /**
161: * Reads up to <code>b.length</code> bytes of data from this file
162: * into an array of bytes. This method blocks until at least one byte
163: * of input is available.
164: *
165: * @param b the buffer into which the data is read.
166: * @return the total number of bytes read into the buffer, or
167: * <code>-1</code> if there is no more data because the end of
168: * this file has been reached.
169: * @exception IOException if an I/O error occurs.
170: * @since JDK1.0
171: */
172: public int read(byte b[]) throws IOException {
173: return readBytes(b, 0, b.length);
174: }
175:
176: /**
177: * Reads <code>b.length</code> bytes from this file into the byte
178: * array. This method reads repeatedly from the file until all the
179: * bytes are read. This method blocks until all the bytes are read,
180: * the end of the stream is detected, or an exception is thrown.
181: *
182: * @param b the buffer into which the data is read.
183: * @exception EOFException if this file reaches the end before reading
184: * all the bytes.
185: * @exception IOException if an I/O error occurs.
186: * @since JDK1.0
187: */
188: public final void readFully(byte b[]) throws IOException {
189: readFully(b, 0, b.length);
190: }
191:
192: /**
193: * Reads exactly <code>len</code> bytes from this file into the byte
194: * array. This method reads repeatedly from the file until all the
195: * bytes are read. This method blocks until all the bytes are read,
196: * the end of the stream is detected, or an exception is thrown.
197: *
198: * @param b the buffer into which the data is read.
199: * @param off the start offset of the data.
200: * @param len the number of bytes to read.
201: * @exception EOFException if this file reaches the end before reading
202: * all the bytes.
203: * @exception IOException if an I/O error occurs.
204: * @since JDK1.0
205: */
206: public final void readFully(byte b[], int off, int len)
207: throws IOException {
208: int n = 0;
209: while (n < len) {
210: int count = this .read(b, off + n, len - n);
211: if (count < 0)
212: throw new EOFException();
213: n += count;
214: }
215: }
216:
217: /**
218: * Skips exactly <code>n</code> bytes of input.
219: * <p>
220: * This method blocks until all the bytes are skipped, the end of
221: * the stream is detected, or an exception is thrown.
222: *
223: * @param n the number of bytes to be skipped.
224: * @return the number of bytes skipped, which is always <code>n</code>.
225: * @exception EOFException if this file reaches the end before skipping
226: * all the bytes.
227: * @exception IOException if an I/O error occurs.
228: * @since JDK1.0
229: */
230: public int skipBytes(int n) throws IOException {
231: seek(getFilePointer() + n);
232: return n;
233: }
234:
235: /**
236: * Returns the current offset in this file.
237: *
238: * @return the offset from the beginning of the file, in bytes,
239: * at which the next read occurs.
240: * @exception IOException if an I/O error occurs.
241: * @since JDK1.0
242: */
243: public native long getFilePointer() throws IOException;
244:
245: /**
246: * Sets the offset from the beginning of this file at which the next
247: * read occurs.
248: *
249: * @param pos the absolute position.
250: * @exception IOException if an I/O error occurs.
251: * @since JDK1.0
252: */
253: public native void seek(long pos) throws IOException;
254:
255: /**
256: * Returns the length of this file.
257: *
258: * @return the length of this file.
259: * @exception IOException if an I/O error occurs.
260: * @since JDK1.0
261: */
262: public native long length() throws IOException;
263:
264: /**
265: * Closes this random access file stream and releases any system
266: * resources associated with the stream.
267: *
268: * @exception IOException if an I/O error occurs.
269: * @since JDK1.0
270: */
271: public native void close() throws IOException;
272:
273: //
274: // Some "reading Java data types" methods stolen from
275: // DataInputStream.
276: //
277:
278: /**
279: * Reads a <code>boolean</code> from this file. This method reads a
280: * single byte from the file. A value of <code>0</code> represents
281: * <code>false</code>. Any other value represents <code>true</code>.
282: * This method blocks until the byte is read, the end of the stream
283: * is detected, or an exception is thrown.
284: *
285: * @return the <code>boolean</code> value read.
286: * @exception EOFException if this file has reached the end.
287: * @exception IOException if an I/O error occurs.
288: * @since JDK1.0
289: */
290: public final boolean readBoolean() throws IOException {
291: int ch = this .read();
292: if (ch < 0)
293: throw new EOFException();
294: return (ch != 0);
295: }
296:
297: /**
298: * Reads a signed 8-bit value from this file. This method reads a
299: * byte from the file. If the byte read is <code>b</code>, where
300: * <code>0 <= b <= 255</code>,
301: * then the result is:
302: * <ul><code>
303: * (byte)(b)
304: *</code></ul>
305: * <p>
306: * This method blocks until the byte is read, the end of the stream
307: * is detected, or an exception is thrown.
308: *
309: * @return the next byte of this file as a signed 8-bit
310: * <code>byte</code>.
311: * @exception EOFException if this file has reached the end.
312: * @exception IOException if an I/O error occurs.
313: * @since JDK1.0
314: */
315: public final byte readByte() throws IOException {
316: int ch = this .read();
317: if (ch < 0)
318: throw new EOFException();
319: return (byte) (ch);
320: }
321:
322: /**
323: * Reads an unsigned 8-bit number from this file. This method reads
324: * a byte from this file and returns that byte.
325: * <p>
326: * This method blocks until the byte is read, the end of the stream
327: * is detected, or an exception is thrown.
328: *
329: * @return the next byte of this file, interpreted as an unsigned
330: * 8-bit number.
331: * @exception EOFException if this file has reached the end.
332: * @exception IOException if an I/O error occurs.
333: * @since JDK1.0
334: */
335: public final int readUnsignedByte() throws IOException {
336: int ch = this .read();
337: if (ch < 0)
338: throw new EOFException();
339: return ch;
340: }
341:
342: /**
343: * Reads a signed 16-bit number from this file. The method reads 2
344: * bytes from this file. If the two bytes read, in order, are
345: * <code>b1</code> and <code>b2</code>, where each of the two values is
346: * between <code>0</code> and <code>255</code>, inclusive, then the
347: * result is equal to:
348: * <ul><code>
349: * (short)((b1 << 8) | b2)
350: * </code></ul>
351: * <p>
352: * This method blocks until the two bytes are read, the end of the
353: * stream is detected, or an exception is thrown.
354: *
355: * @return the next two bytes of this file, interpreted as a signed
356: * 16-bit number.
357: * @exception EOFException if this file reaches the end before reading
358: * two bytes.
359: * @exception IOException if an I/O error occurs.
360: * @since JDK1.0
361: */
362: public final short readShort() throws IOException {
363: int ch1 = this .read();
364: int ch2 = this .read();
365: if ((ch1 | ch2) < 0)
366: throw new EOFException();
367: return (short) ((ch1 << 8) + (ch2 << 0));
368: }
369:
370: /**
371: * Reads an unsigned 16-bit number from this file. This method reads
372: * two bytes from the file. If the bytes read, in order, are
373: * <code>b1</code> and <code>b2</code>, where
374: * <code>0 <= b1, b2 <= 255</code>,
375: * then the result is equal to:
376: * <ul><code>
377: * (b1 << 8) | b2
378: * </code></ul>
379: * <p>
380: * This method blocks until the two bytes are read, the end of the
381: * stream is detected, or an exception is thrown.
382: *
383: * @return the next two bytes of this file, interpreted as an unsigned
384: * 16-bit integer.
385: * @exception EOFException if this file reaches the end before reading
386: * two bytes.
387: * @exception IOException if an I/O error occurs.
388: * @since JDK1.0
389: */
390: public final int readUnsignedShort() throws IOException {
391: int ch1 = this .read();
392: int ch2 = this .read();
393: if ((ch1 | ch2) < 0)
394: throw new EOFException();
395: return (ch1 << 8) + (ch2 << 0);
396: }
397:
398: /**
399: * Reads a Unicode character from this file. This method reads two
400: * bytes from the file. If the bytes read, in order, are
401: * <code>b1</code> and <code>b2</code>, where
402: * <code>0 <= b1, b2 <= 255</code>,
403: * then the result is equal to:
404: * <ul><code>
405: * (char)((b1 << 8) | b2)
406: * </code></ul>
407: * <p>
408: * This method blocks until the two bytes are read, the end of the
409: * stream is detected, or an exception is thrown.
410: *
411: * @return the next two bytes of this file as a Unicode character.
412: * @exception EOFException if this file reaches the end before reading
413: * two bytes.
414: * @exception IOException if an I/O error occurs.
415: * @since JDK1.0
416: */
417: public final char readChar() throws IOException {
418: int ch1 = this .read();
419: int ch2 = this .read();
420: if ((ch1 | ch2) < 0)
421: throw new EOFException();
422: return (char) ((ch1 << 8) + (ch2 << 0));
423: }
424:
425: /**
426: * Reads a signed 32-bit integer from this file. This method reads 4
427: * bytes from the file. If the bytes read, in order, are <code>b1</code>,
428: * <code>b2</code>, <code>b3</code>, and <code>b4</code>, where
429: * <code>0 <= b1, b2, b3, b4 <= 255</code>,
430: * then the result is equal to:
431: * <ul><code>
432: * (b1 << 24) | (b2 << 16) + (b3 << 8) + b4
433: * </code></ul>
434: * <p>
435: * This method blocks until the four bytes are read, the end of the
436: * stream is detected, or an exception is thrown.
437: *
438: * @return the next four bytes of this file, interpreted as an
439: * <code>int</code>.
440: * @exception EOFException if this file reaches the end before reading
441: * four bytes.
442: * @exception IOException if an I/O error occurs.
443: * @since JDK1.0
444: */
445: public final int readInt() throws IOException {
446: int ch1 = this .read();
447: int ch2 = this .read();
448: int ch3 = this .read();
449: int ch4 = this .read();
450: if ((ch1 | ch2 | ch3 | ch4) < 0)
451: throw new EOFException();
452: return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
453: }
454:
455: /**
456: * Reads a signed 64-bit integer from this file. This method reads eight
457: * bytes from the file. If the bytes read, in order, are
458: * <code>b1</code>, <code>b2</code>, <code>b3</code>,
459: * <code>b4</code>, <code>b5</code>, <code>b6</code>,
460: * <code>b7</code>, and <code>b8,</code> where:
461: * <ul><code>
462: * 0 <= b1, b2, b3, b4, b5, b6, b7, b8 <=255,
463: * </code></ul>
464: * <p>
465: * then the result is equal to:
466: * <p><blockquote><pre>
467: * ((long)b1 << 56) + ((long)b2 << 48)
468: * + ((long)b3 << 40) + ((long)b4 << 32)
469: * + ((long)b5 << 24) + ((long)b6 << 16)
470: * + ((long)b7 << 8) + b8
471: * </pre></blockquote>
472: * <p>
473: * This method blocks until the eight bytes are read, the end of the
474: * stream is detected, or an exception is thrown.
475: *
476: * @return the next eight bytes of this file, interpreted as a
477: * <code>long</code>.
478: * @exception EOFException if this file reaches the end before reading
479: * eight bytes.
480: * @exception IOException if an I/O error occurs.
481: * @since JDK1.0
482: */
483: public final long readLong() throws IOException {
484: return ((long) (readInt()) << 32) + (readInt() & 0xFFFFFFFFL);
485: }
486:
487: /**
488: * Reads a <code>float</code> from this file. This method reads an
489: * <code>int</code> value as if by the <code>readInt</code> method
490: * and then converts that <code>int</code> to a <code>float</code>
491: * using the <code>intBitsToFloat</code> method in class
492: * <code>Float</code>.
493: * <p>
494: * This method blocks until the four bytes are read, the end of the
495: * stream is detected, or an exception is thrown.
496: *
497: * @return the next four bytes of this file, interpreted as a
498: * <code>float</code>.
499: * @exception EOFException if this file reaches the end before reading
500: * four bytes.
501: * @exception IOException if an I/O error occurs.
502: * @see java.io.RandomAccessFile#readInt()
503: * @see java.lang.Float#intBitsToFloat(int)
504: * @since JDK1.0
505: */
506: public final float readFloat() throws IOException {
507: return Float.intBitsToFloat(readInt());
508: }
509:
510: /**
511: * Reads a <code>double</code> from this file. This method reads a
512: * <code>long</code> value as if by the <code>readLong</code> method
513: * and then converts that <code>long</code> to a <code>double</code>
514: * using the <code>longBitsToDouble</code> method in
515: * class <code>Double</code>.
516: * <p>
517: * This method blocks until the eight bytes are read, the end of the
518: * stream is detected, or an exception is thrown.
519: *
520: * @return the next eight bytes of this file, interpreted as a
521: * <code>double</code>.
522: * @exception EOFException if this file reaches the end before reading
523: * eight bytes.
524: * @exception IOException if an I/O error occurs.
525: * @see java.io.RandomAccessFile#readLong()
526: * @see java.lang.Double#longBitsToDouble(long)
527: * @since JDK1.0
528: */
529: public final double readDouble() throws IOException {
530: return Double.longBitsToDouble(readLong());
531: }
532:
533: /**
534: * Reads the next line of text from this file. This method
535: * successively reads bytes from the file until it reaches the end of
536: * a line of text.
537: * <p>
538: * A line of text is terminated by a carriage-return character
539: * (<code>'\r'</code>), a newline character (<code>'\n'</code>), a
540: * carriage-return character immediately followed by a newline
541: * character, or the end of the input stream. The line-terminating
542: * character(s), if any, are included as part of the string returned.
543: * <p>
544: * This method blocks until a newline character is read, a carriage
545: * return and the byte following it are read (to see if it is a
546: * newline), the end of the stream is detected, or an exception is thrown.
547: *
548: * @return the next line of text from this file.
549: * @exception IOException if an I/O error occurs.
550: * @since JDK1.0
551: */
552: public final String readLine() throws IOException {
553: StringBuffer input = new StringBuffer();
554: int c;
555: while (((c = read()) != -1) && (c != '\n')) {
556: input.append((char) c);
557: }
558: if ((c == -1) && (input.length() == 0)) {
559: return null;
560: }
561: return input.toString();
562: }
563:
564: /**
565: * Reads in a string from this file. The string has been encoded
566: * using a modified UTF-8 format.
567: * <p>
568: * The first two bytes are read as if by
569: * <code>readUnsignedShort</code>. This value gives the number of
570: * following bytes that are in the encoded string, not
571: * the length of the resulting string. The following bytes are then
572: * interpreted as bytes encoding characters in the UTF-8 format
573: * and are converted into characters.
574: * <p>
575: * This method blocks until all the bytes are read, the end of the
576: * stream is detected, or an exception is thrown.
577: *
578: * @return a Unicode string.
579: * @exception EOFException if this file reaches the end before
580: * reading all the bytes.
581: * @exception IOException if an I/O error occurs.
582: * @exception UTFDataFormatException if the bytes do not represent
583: * valid UTF-8 encoding of a Unicode string.
584: * @see java.io.RandomAccessFile#readUnsignedShort()
585: * @since JDK1.0
586: */
587: public final String readUTF() throws IOException {
588: return DataInputStream.readUTF(this);
589: }
590: }
|