首先需要弄清楚装饰器模式的原理,其次根据以下源代码确定下面三个类在装饰器模式中充当的角色,最后以read函数来分析装饰器模式的实现。
/* FilterInputStream.java -- Base class for classes that filter input
2: Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
3:
4: This file is part of GNU Classpath.
5:
6: GNU Classpath is free software; you can redistribute it and/or modify
7: it under the terms of the GNU General Public License as published by
8: the Free Software Foundation; either version 2, or (at your option)
9: any later version.
10:
11: GNU Classpath is distributed in the hope that it will be useful, but
12: WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU Classpath; see the file COPYING. If not, write to the
18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19: 02110-1301 USA.
20:
21: Linking this library statically or dynamically with other modules is
22: making a combined work based on this library. Thus, the terms and
23: conditions of the GNU General Public License cover the whole
24: combination.
25:
26: As a special exception, the copyright holders of this library give you
27: permission to link this library with independent modules to produce an
28: executable, regardless of the license terms of these independent
29: modules, and to copy and distribute the resulting executable under
30: terms of your choice, provided that you also meet, for each linked
31: independent module, the terms and conditions of the license of that
32: module. An independent module is a module which is not derived from
33: or based on this library. If you modify this library, you may extend
34: this exception to your version of the library, but you are not
35: obligated to do so. If you do not wish to do so, delete this
36: exception statement from your version. */
37:
38:
39: package java.io;
40:
41: /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
42: * "The Java Language Specification", ISBN 0-201-63451-1
43: * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
44: * Status: Believed complete and correct.
45: */
46:
47: /**
48: * This is the common superclass of all standard classes that filter
49: * input. It acts as a layer on top of an underlying <code>InputStream</code>
50: * and simply redirects calls made to it to the subordinate InputStream
51: * instead. Subclasses of this class perform additional filtering
52: * functions in addition to simply redirecting the call.
53: * <p>
54: * This class is not abstract. However, since it only redirects calls
55: * to a subordinate <code>InputStream</code> without adding any functionality
56: * on top of it, this class should not be used directly. Instead, various
57: * subclasses of this class should be used. This is enforced with a
58: * protected constructor. Do not try to hack around it.
59: * <p>
60: * When creating a subclass of <code>FilterInputStream</code>, override the
61: * appropriate methods to implement the desired filtering. However, note
62: * that the <code>read(byte[])</code> method does not need to be overridden
63: * as this class redirects calls to that method to
64: * <code>read(byte[], int, int)</code> instead of to the subordinate
65: * <code>InputStream read(byte[])</code> method.
66: *
67: * @author Aaron M. Renn (arenn@urbanophile.com)
68: * @author Warren Levy (warrenl@cygnus.com)
69: */
70: public class FilterInputStream extends InputStream
71: {
72: /**
73: * This is the subordinate <code>InputStream</code> to which method calls
74: * are redirected
75: */
76: protected InputStream in;
77:
78: /**
79: * Create a <code>FilterInputStream</code> with the specified subordinate
80: * <code>InputStream</code>.
81: *
82: * @param in The subordinate <code>InputStream</code>
83: */
84: protected FilterInputStream(InputStream in)
85: {
86: this.in = in;
87: }
88:
89: /**
90: * Calls the <code>in.mark(int)</code> method.
91: *
92: * @param readlimit The parameter passed to <code>in.mark(int)</code>
93: */
94: public void mark(int readlimit)
95: {
96: in.mark(readlimit);
97: }
98:
99: /**
100: * Calls the <code>in.markSupported()</code> method.
101: *
102: * @return <code>true</code> if mark/reset is supported, <code>false</code>
103: * otherwise
104: */
105: public boolean markSupported()
106: {
107: return in.markSupported();
108: }
109:
110: /**
111: * Calls the <code>in.reset()</code> method.
112: *
113: * @exception IOException If an error occurs
114: */
115: public void reset() throws IOException
116: {
117: in.reset();
118: }
119:
120: /**
121: * Calls the <code>in.available()</code> method.
122: *
123: * @return The value returned from <code>in.available()</code>
124: *
125: * @exception IOException If an error occurs
126: */
127: public int available() throws IOException
128: {
129: return in.available();
130: }
131:
132: /**
133: * Calls the <code>in.skip(long)</code> method
134: *
135: * @param numBytes The requested number of bytes to skip.
136: *
137: * @return The value returned from <code>in.skip(long)</code>
138: *
139: * @exception IOException If an error occurs
140: */
141: public long skip(long numBytes) throws IOException
142: {
143: return in.skip(numBytes);
144: }
145:
146: /**
147: * Calls the <code>in.read()</code> method
148: *
149: * @return The value returned from <code>in.read()</code>
150: *
151: * @exception IOException If an error occurs
152: */
153: public int read() throws IOException
154: {
155: return in.read();
156: }
157:
158: /**
159: * Calls the <code>read(byte[], int, int)</code> overloaded method.
160: * Note that
161: * this method does not redirect its call directly to a corresponding
162: * method in <code>in</code>. This allows subclasses to override only the
163: * three argument version of <code>read</code>.
164: *
165: * @param buf The buffer to read bytes into
166: *
167: * @return The value retured from <code>in.read(byte[], int, int)</code>
168: *
169: * @exception IOException If an error occurs
170: */
171: public int read(byte[] buf) throws IOException
172: {
173: return read(buf, 0, buf.length);
174: }
175:
176: /**
177: * Calls the <code>in.read(byte[], int, int)</code> method.
178: *
179: * @param buf The buffer to read bytes into
180: * @param offset The index into the buffer to start storing bytes
181: * @param len The maximum number of bytes to read.
182: *
183: * @return The value retured from <code>in.read(byte[], int, int)</code>
184: *
185: * @exception IOException If an error occurs
186: */
187: public int read(byte[] buf, int offset, int len) throws IOException
188: {
189: return in.read(buf, offset, len);
190: }
191:
192: /**
193: * This method closes the input stream by closing the input stream that
194: * this object is filtering. Future attempts to access this stream may
195: * throw an exception.
196: *
197: * @exception IOException If an error occurs
198: */
199: public void close() throws IOException
200: {
201: in.close();
202: }
203: }
</pre><pre code_snippet_id="1722382" snippet_file_name="blog_20160620_5_2270228" name="code" class="java">
<pre name="code" class="java"> /* DataInputStream.java -- FilteredInputStream that implements DataInput
2: Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005 Free Software Foundation
3:
4: This file is part of GNU Classpath.
5:
6: GNU Classpath is free software; you can redistribute it and/or modify
7: it under the terms of the GNU General Public License as published by
8: the Free Software Foundation; either version 2, or (at your option)
9: any later version.
10:
11: GNU Classpath is distributed in the hope that it will be useful, but
12: WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU Classpath; see the file COPYING. If not, write to the
18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19: 02110-1301 USA.
20:
21: Linking this library statically or dynamically with other modules is
22: making a combined work based on this library. Thus, the terms and
23: conditions of the GNU General Public License cover the whole
24: combination.
25:
26: As a special exception, the copyright holders of this library give you
27: permission to link this library with independent modules to produce an
28: executable, regardless of the license terms of these independent
29: modules, and to copy and distribute the resulting executable under
30: terms of your choice, provided that you also meet, for each linked
31: independent module, the terms and conditions of the license of that
32: module. An independent module is a module which is not derived from
33: or based on this library. If you modify this library, you may extend
34: this exception to your version of the library, but you are not
35: obligated to do so. If you do not wish to do so, delete this
36: exception statement from your version. */
37:
38: package java.io;
39:
40: /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
41: * "The Java Language Specification", ISBN 0-201-63451-1
42: * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
43: * Status: Believed complete and correct.
44: */
45:
46: /**
47: * This subclass of <code>FilteredInputStream</code> implements the
48: * <code>DataInput</code> interface that provides method for reading primitive
49: * Java data types from a stream.
50: *
51: * @see DataInput
52: *
53: * @author Warren Levy (warrenl@cygnus.com)
54: * @author Aaron M. Renn (arenn@urbanophile.com)
55: * @date October 20, 1998.
56: */
57: public class DataInputStream extends FilterInputStream implements DataInput
58: {
59: // Byte buffer, used to make primitive read calls more efficient.
60: byte[] buf = new byte [8];
61:
62: /**
63: * This constructor initializes a new <code>DataInputStream</code>
64: * to read from the specified subordinate stream.
65: *
66: * @param in The subordinate <code>InputStream</code> to read from
67: */
68: public DataInputStream (InputStream in)
69: {
70: super (in);
71: }
72:
73: /**
74: * This method reads bytes from the underlying stream into the specified
75: * byte array buffer. It will attempt to fill the buffer completely, but
76: * may return a short count if there is insufficient data remaining to be
77: * read to fill the buffer.
78: *
79: * @param b The buffer into which bytes will be read.
80: *
81: * @return The actual number of bytes read, or -1 if end of stream reached
82: * before reading any bytes.
83: *
84: * @exception IOException If an error occurs.
85: */
86: public final int read (byte[] b) throws IOException
87: {
88: return in.read (b, 0, b.length);
89: }
90:
91: /**
92: * This method reads bytes from the underlying stream into the specified
93: * byte array buffer. It will attempt to read <code>len</code> bytes and
94: * will start storing them at position <code>off</code> into the buffer.
95: * This method can return a short count if there is insufficient data
96: * remaining to be read to complete the desired read length.
97: *
98: * @param b The buffer into which bytes will be read.
99: * @param off The offset into the buffer to start storing bytes.
100: * @param len The requested number of bytes to read.
101: *
102: * @return The actual number of bytes read, or -1 if end of stream reached
103: * before reading any bytes.
104: *
105: * @exception IOException If an error occurs.
106: */
107: public final int read (byte[] b, int off, int len) throws IOException
108: {
109: return in.read (b, off, len);
110: }
111:
112: /**
113: * This method reads a Java boolean value from an input stream. It does
114: * so by reading a single byte of data. If that byte is zero, then the
115: * value returned is <code>false</code>. If the byte is non-zero, then
116: * the value returned is <code>true</code>.
117: * <p>
118: * This method can read a <code>boolean</code> written by an object
119: * implementing the <code>writeBoolean()</code> method in the
120: * <code>DataOutput</code> interface.
121: *
122: * @return The <code>boolean</code> value read
123: *
124: * @exception EOFException If end of file is reached before reading
125: * the boolean
126: * @exception IOException If any other error occurs
127: *
128: * @see DataOutput#writeBoolean
129: */
130: public final boolean readBoolean () throws IOException
131: {
132: return convertToBoolean (in.read ());
133: }
134:
135: /**
136: * This method reads a Java byte value from an input stream. The value
137: * is in the range of -128 to 127.
138: * <p>
139: * This method can read a <code>byte</code> written by an object
140: * implementing the <code>writeByte()</code> method in the
141: * <code>DataOutput</code> interface.
142: *
143: * @return The <code>byte</code> value read
144: *
145: * @exception EOFException If end of file is reached before reading the byte
146: * @exception IOException If any other error occurs
147: *
148: * @see DataOutput#writeByte
149: */
150: public final byte readByte () throws IOException
151: {
152: return convertToByte (in.read ());
153: }
154:
155: /**
156: * This method reads a Java <code>char</code> value from an input stream.
157: * It operates by reading two bytes from the stream and converting them to
158: * a single 16-bit Java <code>char</code>. The two bytes are stored most
159: * significant byte first (i.e., "big endian") regardless of the native
160: * host byte ordering.
161: * <p>
162: * As an example, if <code>byte1</code> and <code>byte2</code>
163: * represent the first and second byte read from the stream
164: * respectively, they will be transformed to a <code>char</code> in
165: * the following manner:
166: * <p>
167: * <code>(char)(((byte1 & 0xFF) << 8) | (byte2 & 0xFF)</code>
168: * <p>
169: * This method can read a <code>char</code> written by an object
170: * implementing the <code>writeChar()</code> method in the
171: * <code>DataOutput</code> interface.
172: *
173: * @return The <code>char</code> value read
174: *
175: * @exception EOFException If end of file is reached before reading the char
176: * @exception IOException If any other error occurs
177: *
178: * @see DataOutput#writeChar
179: */
180: public final char readChar () throws IOException
181: {
182: readFully (buf, 0, 2);
183: return convertToChar (buf);
184: }
185:
186: /**
187: * This method reads a Java double value from an input stream. It operates
188: * by first reading a <code>long</code> value from the stream by calling the
189: * <code>readLong()</code> method in this interface, then converts
190: * that <code>long</code> to a <code>double</code> using the
191: * <code>longBitsToDouble</code> method in the class
192: * <code>java.lang.Double</code>
193: * <p>
194: * This method can read a <code>double</code> written by an object
195: * implementing the <code>writeDouble()</code> method in the
196: * <code>DataOutput</code> interface.
197: *
198: * @return The <code>double</code> value read
199: *
200: * @exception EOFException If end of file is reached before reading
201: * the double
202: * @exception IOException If any other error occurs
203: *
204: * @see DataOutput#writeDouble
205: * @see java.lang.Double#longBitsToDouble
206: */
207: public final double readDouble () throws IOException
208: {
209: return Double.longBitsToDouble (readLong ());
210: }
211:
212: /**
213: * This method reads a Java float value from an input stream. It
214: * operates by first reading an <code>int</code> value from the
215: * stream by calling the <code>readInt()</code> method in this
216: * interface, then converts that <code>int</code> to a
217: * <code>float</code> using the <code>intBitsToFloat</code> method
218: * in the class <code>java.lang.Float</code>
219: * <p>
220: * This method can read a <code>float</code> written by an object
221: * implementing the <code>writeFloat()</code> method in the
222: * <code>DataOutput</code> interface.
223: *
224: * @return The <code>float</code> value read
225: *
226: * @exception EOFException If end of file is reached before reading the float
227: * @exception IOException If any other error occurs
228: *
229: * @see DataOutput#writeFloat
230: * @see java.lang.Float#intBitsToFloat
231: */
232: public final float readFloat () throws IOException
233: {
234: return Float.intBitsToFloat (readInt ());
235: }
236:
237: /**
238: * This method reads raw bytes into the passed array until the array is
239: * full. Note that this method blocks until the data is available and
240: * throws an exception if there is not enough data left in the stream to
241: * fill the buffer. Note also that zero length buffers are permitted.
242: * In this case, the method will return immediately without reading any
243: * bytes from the stream.
244: *
245: * @param b The buffer into which to read the data
246: *
247: * @exception EOFException If end of file is reached before filling the
248: * buffer
249: * @exception IOException If any other error occurs
250: */
251: public final void readFully (byte[] b) throws IOException
252: {
253: readFully (b, 0, b.length);
254: }
255:
256: /**
257: * This method reads raw bytes into the passed array <code>buf</code>
258: * starting
259: * <code>offset</code> bytes into the buffer. The number of bytes read
260: * will be
261: * exactly <code>len</code>. Note that this method blocks until the data is
262: * available and throws an exception if there is not enough data left in
263: * the stream to read <code>len</code> bytes. Note also that zero length
264: * buffers are permitted. In this case, the method will return immediately
265: * without reading any bytes from the stream.
266: *
267: * @param buf The buffer into which to read the data
268: * @param offset The offset into the buffer to start storing data
269: * @param len The number of bytes to read into the buffer
270: *
271: * @exception EOFException If end of file is reached before filling the
272: * buffer
273: * @exception IOException If any other error occurs
274: */
275: public final void readFully (byte[] buf, int offset, int len) throws IOException
276: {
277: if (len < 0)
278: throw new IndexOutOfBoundsException("Negative length: " + len);
279:
280: while (len > 0)
281: {
282: // in.read will block until some data is available.
283: int numread = in.read (buf, offset, len);
284: if (numread < 0)
285: throw new EOFException ();
286: len -= numread;
287: offset += numread;
288: }
289: }
290:
291: /**
292: * This method reads a Java <code>int</code> value from an input stream
293: * It operates by reading four bytes from the stream and converting them to
294: * a single Java <code>int</code>. The bytes are stored most
295: * significant byte first (i.e., "big endian") regardless of the native
296: * host byte ordering.
297: * <p>
298: * As an example, if <code>byte1</code> through <code>byte4</code> represent
299: * the first four bytes read from the stream, they will be
300: * transformed to an <code>int</code> in the following manner:
301: * <p>
302: * <code>(int)(((byte1 & 0xFF) << 24) + ((byte2 & 0xFF) << 16) +
303: * ((byte3 & 0xFF)<< 8) + (byte4 & 0xFF)))</code>
304: * <p>
305: * The value returned is in the range of -2147483648 to 2147483647.
306: * <p>
307: * This method can read an <code>int</code> written by an object
308: * implementing the <code>writeInt()</code> method in the
309: * <code>DataOutput</code> interface.
310: *
311: * @return The <code>int</code> value read
312: *
313: * @exception EOFException If end of file is reached before reading the int
314: * @exception IOException If any other error occurs
315: *
316: * @see DataOutput#writeInt
317: */
318: public final int readInt () throws IOException
319: {
320: readFully (buf, 0, 4);
321: return convertToInt (buf);
322: }
323:
324: /**
325: * This method reads the next line of text data from an input
326: * stream. It operates by reading bytes and converting those bytes
327: * to <code>char</code> values by treating the byte read as the low
328: * eight bits of the <code>char</code> and using 0 as the high eight
329: * bits. Because of this, it does not support the full 16-bit
330: * Unicode character set.
331: * <p>
332: * The reading of bytes ends when either the end of file or a line
333: * terminator is encountered. The bytes read are then returned as a
334: * <code>String</code> A line terminator is a byte sequence
335: * consisting of either <code>\r</code>, <code>\n</code> or
336: * <code>\r\n</code>. These termination charaters are discarded and
337: * are not returned as part of the string.
338: * <p>
339: * This method can read data that was written by an object implementing the
340: * <code>writeLine()</code> method in <code>DataOutput</code>.
341: *
342: * @return The line read as a <code>String</code>
343: *
344: * @exception IOException If an error occurs
345: *
346: * @see DataOutput
347: *
348: * @deprecated
349: */
350: public final String readLine() throws IOException
351: {
352: StringBuffer strb = new StringBuffer();
353:
354: while (true)
355: {
356: int c = in.read();
357: if (c == -1) // got an EOF
358: return strb.length() > 0 ? strb.toString() : null;
359: if (c == '\r')
360: {
361: int next_c = in.read();
362: if (next_c != '\n' && next_c != -1)
363: {
364: if (!(in instanceof PushbackInputStream))
365: in = new PushbackInputStream(in);
366: ((PushbackInputStream) in).unread(next_c);
367: }
368: break;
369: }
370: if (c == '\n')
371: break;
372: strb.append((char) c);
373: }
374:
375: return strb.length() > 0 ? strb.toString() : "";
376: }
377:
378: /**
379: * This method reads a Java <code>long</code> value from an input stream
380: * It operates by reading eight bytes from the stream and converting them to
381: * a single Java <code>long</code>. The bytes are stored most
382: * significant byte first (i.e., "big endian") regardless of the native
383: * host byte ordering.
384: * <p>
385: * As an example, if <code>byte1</code> through <code>byte8</code> represent
386: * the first eight bytes read from the stream, they will be
387: * transformed to an <code>long</code> in the following manner:
388: * <p>
389: * <code>(long)(((byte1 & 0xFF) << 56) + ((byte2 & 0xFF) << 48) +
390: * ((byte3 & 0xFF) << 40) + ((byte4 & 0xFF) << 32) +
391: * ((byte5 & 0xFF) << 24) + ((byte6 & 0xFF) << 16) +
392: * ((byte7 & 0xFF) << 8) + (byte8 & 0xFF)))
393: * </code>
394: * <p>
395: * The value returned is in the range of -9223372036854775808 to
396: * 9223372036854775807.
397: * <p>
398: * This method can read an <code>long</code> written by an object
399: * implementing the <code>writeLong()</code> method in the
400: * <code>DataOutput</code> interface.
401: *
402: * @return The <code>long</code> value read
403: *
404: * @exception EOFException If end of file is reached before reading the long
405: * @exception IOException If any other error occurs
406: *
407: * @see DataOutput#writeLong
408: */
409: public final long readLong () throws IOException
410: {
411: readFully (buf, 0, 8);
412: return convertToLong (buf);
413: }
414:
415: /**
416: * This method reads a signed 16-bit value into a Java in from the
417: * stream. It operates by reading two bytes from the stream and
418: * converting them to a single 16-bit Java <code>short</code>. The
419: * two bytes are stored most significant byte first (i.e., "big
420: * endian") regardless of the native host byte ordering.
421: * <p>
422: * As an example, if <code>byte1</code> and <code>byte2</code>
423: * represent the first and second byte read from the stream
424: * respectively, they will be transformed to a <code>short</code>. in
425: * the following manner:
426: * <p>
427: * <code>(short)(((byte1 & 0xFF) << 8) | (byte2 & 0xFF))</code>
428: * <p>
429: * The value returned is in the range of -32768 to 32767.
430: * <p>
431: * This method can read a <code>short</code> written by an object
432: * implementing the <code>writeShort()</code> method in the
433: * <code>DataOutput</code> interface.
434: *
435: * @return The <code>short</code> value read
436: *
437: * @exception EOFException If end of file is reached before reading the value
438: * @exception IOException If any other error occurs
439: *
440: * @see DataOutput#writeShort
441: */
442: public final short readShort () throws IOException
443: {
444: readFully (buf, 0, 2);
445: return convertToShort (buf);
446: }
447:
448: /**
449: * This method reads 8 unsigned bits into a Java <code>int</code>
450: * value from the stream. The value returned is in the range of 0 to
451: * 255.
452: * <p>
453: * This method can read an unsigned byte written by an object
454: * implementing the <code>writeUnsignedByte()</code> method in the
455: * <code>DataOutput</code> interface.
456: *
457: * @return The unsigned bytes value read as a Java <code>int</code>.
458: *
459: * @exception EOFException If end of file is reached before reading the value
460: * @exception IOException If any other error occurs
461: *
462: * @see DataOutput#writeByte
463: */
464: public final int readUnsignedByte () throws IOException
465: {
466: return convertToUnsignedByte (in.read ());
467: }
468:
469: /**
470: * This method reads 16 unsigned bits into a Java int value from the stream.
471: * It operates by reading two bytes from the stream and converting them to
472: * a single Java <code>int</code> The two bytes are stored most
473: * significant byte first (i.e., "big endian") regardless of the native
474: * host byte ordering.
475: * <p>
476: * As an example, if <code>byte1</code> and <code>byte2</code>
477: * represent the first and second byte read from the stream
478: * respectively, they will be transformed to an <code>int</code> in
479: * the following manner:
480: * <p>
481: * <code>(int)(((byte1 & 0xFF) << 8) + (byte2 & 0xFF))</code>
482: * <p>
483: * The value returned is in the range of 0 to 65535.
484: * <p>
485: * This method can read an unsigned short written by an object
486: * implementing the <code>writeUnsignedShort()</code> method in the
487: * <code>DataOutput</code> interface.
488: *
489: * @return The unsigned short value read as a Java <code>int</code>
490: *
491: * @exception EOFException If end of file is reached before reading the value
492: * @exception IOException If any other error occurs
493: *
494: * @see DataOutput#writeShort
495: */
496: public final int readUnsignedShort () throws IOException
497: {
498: readFully (buf, 0, 2);
499: return convertToUnsignedShort (buf);
500: }
501:
502: /**
503: * This method reads a <code>String</code> from an input stream that
504: * is encoded in a modified UTF-8 format. This format has a leading
505: * two byte sequence that contains the remaining number of bytes to
506: * read. This two byte sequence is read using the
507: * <code>readUnsignedShort()</code> method of this interface.
508: * <p>
509: * After the number of remaining bytes have been determined, these
510: * bytes are read an transformed into <code>char</code> values.
511: * These <code>char</code> values are encoded in the stream using
512: * either a one, two, or three byte format. The particular format
513: * in use can be determined by examining the first byte read.
514: * <p>
515: * If the first byte has a high order bit of 0, then that character
516: * consists on only one byte. This character value consists of
517: * seven bits that are at positions 0 through 6 of the byte. As an
518: * example, if <code>byte1</code> is the byte read from the stream,
519: * it would be converted to a <code>char</code> like so:
520: * <p>
521: * <code>(char)byte1</code>
522: * <p>
523: * If the first byte has 110 as its high order bits, then the
524: * character consists of two bytes. The bits that make up the character
525: * value are in positions 0 through 4 of the first byte and bit positions
526: * 0 through 5 of the second byte. (The second byte should have
527: * 10 as its high order bits). These values are in most significant
528: * byte first (i.e., "big endian") order.
529: * <p>
530: * As an example, if <code>byte1</code> and <code>byte2</code> are
531: * the first two bytes read respectively, and the high order bits of
532: * them match the patterns which indicate a two byte character
533: * encoding, then they would be converted to a Java
534: * <code>char</code> like so:
535: * <p>
536: * <code>(char)(((byte1 & 0x1F) << 6) | (byte2 & 0x3F))</code>
537: * <p>
538: * If the first byte has a 1110 as its high order bits, then the
539: * character consists of three bytes. The bits that make up the character
540: * value are in positions 0 through 3 of the first byte and bit positions
541: * 0 through 5 of the other two bytes. (The second and third bytes should
542: * have 10 as their high order bits). These values are in most
543: * significant byte first (i.e., "big endian") order.
544: * <p>
545: * As an example, if <code>byte1</code> <code>byte2</code> and
546: * <code>byte3</code> are the three bytes read, and the high order
547: * bits of them match the patterns which indicate a three byte
548: * character encoding, then they would be converted to a Java
549: * <code>char</code> like so:
550: * <p>
551: * <code>(char)(((byte1 & 0x0F) << 12) | ((byte2 & 0x3F) << 6) |
552: * (byte3 & 0x3F))</code>
553: * <p>
554: * Note that all characters are encoded in the method that requires
555: * the fewest number of bytes with the exception of the character
556: * with the value of <code>\u0000</code> which is encoded as two
557: * bytes. This is a modification of the UTF standard used to
558: * prevent C language style <code>NUL</code> values from appearing
559: * in the byte stream.
560: * <p>
561: * This method can read data that was written by an object implementing the
562: * <code>writeUTF()</code> method in <code>DataOutput</code>
563: *
564: * @return The <code>String</code> read
565: *
566: * @exception EOFException If end of file is reached before reading
567: * the String
568: * @exception UTFDataFormatException If the data is not in UTF-8 format
569: * @exception IOException If any other error occurs
570: *
571: * @see DataOutput#writeUTF
572: */
573: public final String readUTF () throws IOException
574: {
575: return readUTF (this);
576: }
577:
578: /**
579: * This method reads a String encoded in UTF-8 format from the
580: * specified <code>DataInput</code> source.
581: *
582: * @param in The <code>DataInput</code> source to read from
583: *
584: * @return The String read from the source
585: *
586: * @exception IOException If an error occurs
587: *
588: * @see DataInput#readUTF
589: */
590: public static final String readUTF(DataInput in) throws IOException
591: {
592: final int UTFlen = in.readUnsignedShort ();
593: byte[] buf = new byte [UTFlen];
594:
595: // This blocks until the entire string is available rather than
596: // doing partial processing on the bytes that are available and then
597: // blocking. An advantage of the latter is that Exceptions
598: // could be thrown earlier. The former is a bit cleaner.
599: in.readFully (buf, 0, UTFlen);
600:
601: return convertFromUTF (buf);
602: }
603:
604: /**
605: * This method attempts to skip and discard the specified number of bytes
606: * in the input stream. It may actually skip fewer bytes than requested.
607: * This method will not skip any bytes if passed a negative number of bytes
608: * to skip.
609: *
610: * @param n The requested number of bytes to skip.
611: *
612: * @return The requested number of bytes to skip.
613: *
614: * @exception IOException If an error occurs.
615: * @specnote The JDK docs claim that this returns the number of bytes
616: * actually skipped. The JCL claims that this method can throw an
617: * EOFException. Neither of these appear to be true in the JDK 1.3's
618: * implementation. This tries to implement the actual JDK behaviour.
619: */
620: public final int skipBytes (int n) throws IOException
621: {
622: if (n <= 0)
623: return 0;
624: try
625: {
626: return (int) in.skip (n);
627: }
628: catch (EOFException x)
629: {
630: // do nothing.
631: }
632: return n;
633: }
634:
635: static boolean convertToBoolean (int b) throws EOFException
636: {
637: if (b < 0)
638: throw new EOFException ();
639:
640: return (b != 0);
641: }
642:
643: static byte convertToByte (int i) throws EOFException
644: {
645: if (i < 0)
646: throw new EOFException ();
647:
648: return (byte) i;
649: }
650:
651: static int convertToUnsignedByte (int i) throws EOFException
652: {
653: if (i < 0)
654: throw new EOFException ();
655:
656: return (i & 0xFF);
657: }
658:
659: static char convertToChar (byte[] buf)
660: {
661: return (char) ((buf [0] << 8)
662: | (buf [1] & 0xff));
663: }
664:
665: static short convertToShort (byte[] buf)
666: {
667: return (short) ((buf [0] << 8)
668: | (buf [1] & 0xff));
669: }
670:
671: static int convertToUnsignedShort (byte[] buf)
672: {
673: return (((buf [0] & 0xff) << 8)
674: | (buf [1] & 0xff));
675: }
676:
677: static int convertToInt (byte[] buf)
678: {
679: return (((buf [0] & 0xff) << 24)
680: | ((buf [1] & 0xff) << 16)
681: | ((buf [2] & 0xff) << 8)
682: | (buf [3] & 0xff));
683: }
684:
685: static long convertToLong (byte[] buf)
686: {
687: return (((long)(buf [0] & 0xff) << 56) |
688: ((long)(buf [1] & 0xff) << 48) |
689: ((long)(buf [2] & 0xff) << 40) |
690: ((long)(buf [3] & 0xff) << 32) |
691: ((long)(buf [4] & 0xff) << 24) |
692: ((long)(buf [5] & 0xff) << 16) |
693: ((long)(buf [6] & 0xff) << 8) |
694: ((long)(buf [7] & 0xff)));
695: }
696:
697: // FIXME: This method should be re-thought. I suspect we have multiple
698: // UTF-8 decoders floating around. We should use the standard charset
699: // converters, maybe and adding a direct call into one of the new
700: // NIO converters for a super-fast UTF8 decode.
701: static String convertFromUTF (byte[] buf)
702: throws EOFException, UTFDataFormatException
703: {
704: // Give StringBuffer an initial estimated size to avoid
705: // enlarge buffer frequently
706: StringBuffer strbuf = new StringBuffer (buf.length / 2 + 2);
707:
708: for (int i = 0; i < buf.length; )
709: {
710: if ((buf [i] & 0x80) == 0) // bit pattern 0xxxxxxx
711: strbuf.append ((char) (buf [i++] & 0xFF));
712: else if ((buf [i] & 0xE0) == 0xC0) // bit pattern 110xxxxx
713: {
714: if (i + 1 >= buf.length
715: || (buf [i + 1] & 0xC0) != 0x80)
716: throw new UTFDataFormatException ();
717:
718: strbuf.append((char) (((buf [i++] & 0x1F) << 6)
719: | (buf [i++] & 0x3F)));
720: }
721: else if ((buf [i] & 0xF0) == 0xE0) // bit pattern 1110xxxx
722: {
723: if (i + 2 >= buf.length
724: || (buf [i + 1] & 0xC0) != 0x80
725: || (buf [i + 2] & 0xC0) != 0x80)
726: throw new UTFDataFormatException ();
727:
728: strbuf.append ((char) (((buf [i++] & 0x0F) << 12)
729: | ((buf [i++] & 0x3F) << 6)
730: | (buf [i++] & 0x3F)));
731: }
732: else // must be ((buf [i] & 0xF0) == 0xF0 || (buf [i] & 0xC0) == 0x80)
733: throw new UTFDataFormatException (); // bit patterns 1111xxxx or
734: // 10xxxxxx
735: }
736:
737: return strbuf.toString ();
738: }
739: }
</pre><pre code_snippet_id="1722382" snippet_file_name="blog_20160620_6_9063861" name="code" class="java"><pre style="background-color: rgb(255, 255, 255);"><pre name="code" class="java">1: /* FileInputStream.java -- An input stream that reads from disk files.
2: Copyright (C) 1998, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
3:
4: This file is part of GNU Classpath.
5:
6: GNU Classpath is free software; you can redistribute it and/or modify
7: it under the terms of the GNU General Public License as published by
8: the Free Software Foundation; either version 2, or (at your option)
9: any later version.
10:
11: GNU Classpath is distributed in the hope that it will be useful, but
12: WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU Classpath; see the file COPYING. If not, write to the
18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19: 02110-1301 USA.
20:
21: Linking this library statically or dynamically with other modules is
22: making a combined work based on this library. Thus, the terms and
23: conditions of the GNU General Public License cover the whole
24: combination.
25:
26: As a special exception, the copyright holders of this library give you
27: permission to link this library with independent modules to produce an
28: executable, regardless of the license terms of these independent
29: modules, and to copy and distribute the resulting executable under
30: terms of your choice, provided that you also meet, for each linked
31: independent module, the terms and conditions of the license of that
32: module. An independent module is a module which is not derived from
33: or based on this library. If you modify this library, you may extend
34: this exception to your version of the library, but you are not
35: obligated to do so. If you do not wish to do so, delete this
36: exception statement from your version. */
37:
38:
39: package java.io;
40:
41: import gnu.java.nio.FileChannelImpl;
42:
43: import java.nio.ByteBuffer;
44: import java.nio.channels.FileChannel;
45:
46: /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
47: * "The Java Language Specification", ISBN 0-201-63451-1
48: * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
49: * Status: Believed complete and correct.
50: */
51:
52: /**
53: * This class is a stream that reads its bytes from a file.
54: *
55: * @author Aaron M. Renn (arenn@urbanophile.com)
56: * @author Warren Levy (warrenl@cygnus.com)
57: */
58: public class FileInputStream extends InputStream
59: {
60: /**
61: * This is the native file handle for the file this stream is reading from
62: */
63: private FileDescriptor fd;
64:
65: private FileChannelImpl ch;
66:
67: /**
68: * This method initializes a <code>FileInputStream</code> to read from the
69: * specified named file. A security check is first made to determine
70: * whether or not access to this file is allowed. This is done by
71: * calling the <code>checkRead()</code> method of the
72: * <code>SecurityManager</code>
73: * (if one exists) with the name of this file. An exception is thrown
74: * if reading is not allowed. If the file does not exist, an exception
75: * is also thrown.
76: *
77: * @param name The name of the file this stream should read from
78: *
79: * @exception SecurityException If read access to the file is not allowed
80: * @exception FileNotFoundException If the file does not exist
81: * or if it is a directory
82: */
83: public FileInputStream(String name) throws FileNotFoundException
84: {
85: this(new File(name));
86: }
87:
88: /**
89: * This method initializes a <code>FileInputStream</code> to read from the
90: * specified <code>File</code> object. A security check is first
91: * made to determine
92: * whether or not access to this file is allowed. This is done by
93: * calling the <code>checkRead()</code> method of the
94: * <code>SecurityManager</code>
95: * (if one exists) with the name of this file. An exception is thrown
96: * if reading is not allowed. If the file does not exist, an exception
97: * is also thrown.
98: *
99: * @param file The <code>File</code> object this stream should read from
100: *
101: * @exception SecurityException If read access to the file is not allowed
102: * @exception FileNotFoundException If the file does not exist
103: * or if it is a directory.
104: */
105: public FileInputStream(File file) throws FileNotFoundException
106: {
107: SecurityManager s = System.getSecurityManager();
108: if (s != null)
109: s.checkRead(file.getPath());
110:
111: try
112: {
113: ch = FileChannelImpl.create(file, FileChannelImpl.READ);
114: }
115: catch (FileNotFoundException fnfe)
116: {
117: throw fnfe;
118: }
119: catch (IOException ioe)
120: {
121: FileNotFoundException fnfe = new FileNotFoundException(file.getPath());
122: fnfe.initCause(ioe);
123: throw fnfe;
124: }
125: }
126:
127: /**
128: * This method initializes a <code>FileInputStream</code> to read from the
129: * specified <code>FileDescriptor</code> object. A security
130: * check is first made to
131: * determine whether or not access to this file is allowed. This is done by
132: * calling the <code>checkRead()</code> method of the
133: * <code>SecurityManager</code>
134: * (if one exists) with the specified <code>FileDescriptor</code>
135: * An exception is
136: * thrown if reading is not allowed.
137: *
138: * @param fdObj The <code>FileDescriptor</code> object this stream
139: * should read from
140: *
141: * @exception SecurityException If read access to the file is not allowed
142: */
143: public FileInputStream(FileDescriptor fdObj)
144: {
145: SecurityManager s = System.getSecurityManager();
146: if (s != null)
147: s.checkRead(fdObj);
148:
149: fd = fdObj;
150: ch = (FileChannelImpl) fdObj.channel;
151: }
152:
153: FileInputStream(FileChannelImpl ch)
154: {
155: this.ch = ch;
156: }
157:
158: /**
159: * This method returns the number of bytes that can be read from this
160: * stream before a read can block. A return of 0 indicates that blocking
161: * might (or might not) occur on the very next read attempt.
162: * <p>
163: * This method returns the number of unread bytes remaining in the file if
164: * the descriptor being read from is an actual file. If this method is
165: * reading from a ''special'' file such a the standard input, this method
166: * will return the appropriate value for the stream being read.
167: * <p>
168: * Be aware that reads on plain files that do not reside locally might
169: * possibly block even if this method says they should not. For example,
170: * a remote server might crash, preventing an NFS mounted file from being
171: * read.
172: *
173: * @return The number of bytes that can be read before blocking could occur
174: *
175: * @exception IOException If an error occurs
176: */
177: public int available() throws IOException
178: {
179: return ch.available();
180: }
181:
182: /**
183: * This method closes the stream. Any futher attempts to read from the
184: * stream will likely generate an IOException since the underlying file
185: * will be closed.
186: *
187: * @exception IOException If an error occurs.
188: */
189: public void close() throws IOException
190: {
191: ch.close();
192: }
193:
194: protected void finalize() throws IOException
195: {
196: // We don't actually need this, but we include it because it is
197: // mentioned in the JCL.
198: }
199:
200: /**
201: * This method returns a <code>FileDescriptor</code> object representing the
202: * underlying native file handle of the file this stream is reading
203: * from
204: *
205: * @return A <code>FileDescriptor</code> for this stream
206: *
207: * @exception IOException If an error occurs
208: */
209: public final FileDescriptor getFD() throws IOException
210: {
211: synchronized (this)
212: {
213: if (fd == null)
214: fd = new FileDescriptor (ch);
215: return fd;
216: }
217: }
218:
219: /**
220: * This method reads an unsigned byte from the input stream and returns it
221: * as an int in the range of 0-255. This method also will return -1 if
222: * the end of the stream has been reached.
223: * <p>
224: * This method will block until the byte can be read.
225: *
226: * @return The byte read or -1 if end of stream
227: *
228: * @exception IOException If an error occurs
229: */
230: public int read() throws IOException
231: {
232: return ch.read();
233: }
234:
235: /**
236: * This method reads bytes from a stream and stores them into a caller
237: * supplied buffer. This method attempts to completely fill the buffer,
238: * but can return before doing so. The actual number of bytes read is
239: * returned as an int. A -1 is returned to indicate the end of the stream.
240: * <p>
241: * This method will block until some data can be read.
242: * <p>
243: * This method operates by calling an overloaded read method like so:
244: * <code>read(buf, 0, buf.length)</code>
245: *
246: * @param buf The buffer into which the bytes read will be stored.
247: *
248: * @return The number of bytes read or -1 if end of stream.
249: *
250: * @exception IOException If an error occurs.
251: */
252: public int read(byte[] buf) throws IOException
253: {
254: return read(buf, 0, buf.length);
255: }
256:
257: /**
258: * This method read bytes from a stream and stores them into a caller
259: * supplied buffer. It starts storing the data at index
260: * <code>offset</code> into
261: * the buffer and attempts to read <code>len</code> bytes. This method can
262: * return before reading the number of bytes requested. The actual number
263: * of bytes read is returned as an int. A -1 is returned to indicate the
264: * end of the stream.
265: * <p>
266: * This method will block until some data can be read.
267: *
268: * @param buf The array into which the bytes read should be stored
269: * @param offset The offset into the array to start storing bytes
270: * @param len The requested number of bytes to read
271: *
272: * @return The actual number of bytes read, or -1 if end of stream.
273: *
274: * @exception IOException If an error occurs.
275: */
276: public int read(byte[] buf, int offset, int len) throws IOException
277: {
278: if (offset < 0
279: || len < 0
280: || offset + len > buf.length)
281: throw new ArrayIndexOutOfBoundsException();
282:
283: return ch.read(ByteBuffer.wrap(buf, offset, len));
284: }
285:
286: /**
287: * This method skips the specified number of bytes in the stream. It
288: * returns the actual number of bytes skipped, which may be less than the
289: * requested amount.
290: * <p>
291: * @param numBytes The requested number of bytes to skip
292: *
293: * @return The actual number of bytes skipped.
294: *
295: * @exception IOException If an error occurs
296: */
297: public synchronized long skip (long numBytes) throws IOException
298: {
299: if (numBytes < 0)
300: throw new IllegalArgumentException ("Can't skip negative bytes: " +
301: numBytes);
302:
303: if (numBytes == 0)
304: return 0;
305:
306: long oldPos = ch.position ();
307: ch.position(oldPos + numBytes);
308: return ch.position() - oldPos;
309: }
310:
311: /**
312: * This method creates a java.nio.channels.FileChannel.
313: * Nio does not allow one to create a file channel directly.
314: * A file channel must be created by first creating an instance of
315: * Input/Output/RandomAccessFile and invoking the getChannel() method on it.
316: */
317: public synchronized FileChannel getChannel ()
318: {
319: return ch;
320: }
321:
322: } // class FileInputStream