42 |
import java.nio.channels.FileChannel; |
import java.nio.channels.FileChannel; |
43 |
import gnu.java.nio.FileChannelImpl; |
import gnu.java.nio.FileChannelImpl; |
44 |
|
|
45 |
|
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 |
46 |
|
* "The Java Language Specification", ISBN 0-201-63451-1 |
47 |
|
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com. |
48 |
|
* Status: Believed complete and correct. |
49 |
|
*/ |
50 |
|
|
51 |
/** |
/** |
52 |
* This class is a stream that reads its bytes from a file. |
* This class is a stream that reads its bytes from a file. |
53 |
* |
* |
54 |
* @author Aaron M. Renn (arenn@urbanophile.com) |
* @author Aaron M. Renn <arenn@urbanophile.com> |
55 |
|
* @author Warren Levy <warrenl@cygnus.com> |
56 |
*/ |
*/ |
57 |
public class FileInputStream extends InputStream |
public class FileInputStream extends InputStream |
58 |
{ |
{ |
|
private FileChannel ch; /* cached associated file-channel */ |
|
|
|
|
59 |
/** |
/** |
60 |
* This is the native file handle for the file this stream is reading from |
* This is the native file handle for the file this stream is reading from |
61 |
*/ |
*/ |
62 |
private FileDescriptor fd; |
private FileDescriptor fd; |
63 |
|
|
64 |
/** |
private FileChannel ch; /* cached associated file-channel */ |
|
* This method initializes a <code>FileInputStream</code> to read from the |
|
|
* specified <code>File</code> object. A security check is first |
|
|
* made to determine |
|
|
* whether or not access to this file is allowed. This is done by |
|
|
* calling the <code>checkRead()</code> method of the |
|
|
* <code>SecurityManager</code> |
|
|
* (if one exists) with the name of this file. An exception is thrown |
|
|
* if reading is not allowed. If the file does not exist, an exception |
|
|
* is also thrown. |
|
|
* |
|
|
* @param file The <code>File</code> object this stream should read from |
|
|
* |
|
|
* @exception SecurityException If read access to the file is not allowed |
|
|
* @exception FileNotFoundException If the file does not exist. |
|
|
*/ |
|
|
public FileInputStream(File file) throws FileNotFoundException |
|
|
{ |
|
|
this(file.getPath()); |
|
|
} |
|
65 |
|
|
66 |
/** |
/** |
67 |
* This method initializes a <code>FileInputStream</code> to read from the |
* This method initializes a <code>FileInputStream</code> to read from the |
80 |
*/ |
*/ |
81 |
public FileInputStream(String name) throws FileNotFoundException |
public FileInputStream(String name) throws FileNotFoundException |
82 |
{ |
{ |
83 |
SecurityManager sm = System.getSecurityManager(); |
SecurityManager s = System.getSecurityManager(); |
84 |
if (sm != null) |
if (s != null) |
85 |
sm.checkRead(name); |
s.checkRead(name); |
86 |
|
|
87 |
fd = new FileDescriptor(); |
fd = new FileDescriptor(); |
88 |
|
|
98 |
|
|
99 |
/** |
/** |
100 |
* This method initializes a <code>FileInputStream</code> to read from the |
* This method initializes a <code>FileInputStream</code> to read from the |
101 |
* specified <code>FileDescriptor</code> object. A security |
* specified <code>File</code> object. A security check is first |
102 |
* check is first made to |
* made to determine |
103 |
|
* whether or not access to this file is allowed. This is done by |
104 |
|
* calling the <code>checkRead()</code> method of the |
105 |
|
* <code>SecurityManager</code> |
106 |
|
* (if one exists) with the name of this file. An exception is thrown |
107 |
|
* if reading is not allowed. If the file does not exist, an exception |
108 |
|
* is also thrown. |
109 |
|
* |
110 |
|
* @param file The <code>File</code> object this stream should read from |
111 |
|
* |
112 |
|
* @exception SecurityException If read access to the file is not allowed |
113 |
|
* @exception FileNotFoundException If the file does not exist. |
114 |
|
*/ |
115 |
|
public FileInputStream(File file) throws FileNotFoundException |
116 |
|
{ |
117 |
|
this(file.getPath()); |
118 |
|
} |
119 |
|
|
120 |
|
/** |
121 |
|
* This method initializes a <code>FileInputStream</code> to read from the |
122 |
|
* specified <code>FileDescriptor</code> object. A security |
123 |
|
* check is first made to |
124 |
* determine whether or not access to this file is allowed. This is done by |
* determine whether or not access to this file is allowed. This is done by |
125 |
* calling the <code>checkRead()</code> method of the |
* calling the <code>checkRead()</code> method of the |
126 |
* <code>SecurityManager</code> |
* <code>SecurityManager</code> |
133 |
* |
* |
134 |
* @exception SecurityException If read access to the file is not allowed |
* @exception SecurityException If read access to the file is not allowed |
135 |
*/ |
*/ |
136 |
public FileInputStream(FileDescriptor fd) throws SecurityException |
public FileInputStream(FileDescriptor fdObj) |
137 |
{ |
{ |
138 |
// Hmmm, no other exception but this one to throw, but if the descriptor |
// Hmmm, no other exception but this one to throw, but if the descriptor |
139 |
// isn't valid, we surely don't have "permission" to read from it. |
// isn't valid, we surely don't have "permission" to read from it. |
140 |
if (!fd.valid()) |
if (!fdObj.valid()) |
141 |
throw new SecurityException("Invalid FileDescriptor"); |
throw new SecurityException("Invalid FileDescriptor"); |
142 |
|
|
143 |
SecurityManager sm = System.getSecurityManager(); |
SecurityManager s = System.getSecurityManager(); |
144 |
if (sm != null) |
if (s != null) |
145 |
sm.checkRead(fd); |
s.checkRead(fdObj); |
146 |
|
|
147 |
this.fd = fd; |
this.fd = fdObj; |
|
} |
|
|
|
|
|
/** |
|
|
* This method returns a <code>FileDescriptor</code> object representing the |
|
|
* underlying native file handle of the file this stream is reading |
|
|
* from |
|
|
* |
|
|
* @return A <code>FileDescriptor</code> for this stream |
|
|
* |
|
|
* @exception IOException If an error occurs |
|
|
*/ |
|
|
public final FileDescriptor getFD() throws IOException |
|
|
{ |
|
|
return(fd); |
|
148 |
} |
} |
149 |
|
|
150 |
/** |
/** |
168 |
*/ |
*/ |
169 |
public int available() throws IOException |
public int available() throws IOException |
170 |
{ |
{ |
171 |
return(fd.available()); |
return fd.available(); |
172 |
} |
} |
173 |
|
|
174 |
/** |
/** |
175 |
* This method skips the specified number of bytes in the stream. It |
* This method closes the stream. Any futher attempts to read from the |
176 |
* returns the actual number of bytes skipped, which may be less than the |
* stream will likely generate an IOException since the underlying file |
177 |
* requested amount. |
* will be closed. |
|
* <p> |
|
|
* @param numBytes The requested number of bytes to skip |
|
178 |
* |
* |
179 |
* @return The actual number of bytes skipped. |
* @exception IOException If an error occurs. |
180 |
|
*/ |
181 |
|
public void close() throws IOException |
182 |
|
{ |
183 |
|
fd.close(); |
184 |
|
} |
185 |
|
|
186 |
|
/** |
187 |
|
* This method returns a <code>FileDescriptor</code> object representing the |
188 |
|
* underlying native file handle of the file this stream is reading |
189 |
|
* from |
190 |
|
* |
191 |
|
* @return A <code>FileDescriptor</code> for this stream |
192 |
* |
* |
193 |
* @exception IOException If an error occurs |
* @exception IOException If an error occurs |
194 |
*/ |
*/ |
195 |
public synchronized long skip(long numBytes) throws IOException |
public final FileDescriptor getFD() throws IOException |
196 |
{ |
{ |
197 |
if (numBytes < 0) |
return fd; |
|
throw new IllegalArgumentException("Can't skip negative bytes: " + |
|
|
numBytes); |
|
|
|
|
|
if (numBytes == 0) |
|
|
return(0); |
|
|
|
|
|
long curPos = fd.getFilePointer(); |
|
|
long newPos = fd.seek(numBytes, fd.CUR, true); |
|
|
|
|
|
return(newPos-curPos); |
|
198 |
} |
} |
199 |
|
|
200 |
/** |
/** |
210 |
*/ |
*/ |
211 |
public int read() throws IOException |
public int read() throws IOException |
212 |
{ |
{ |
213 |
return(fd.read()); |
return fd.read(); |
214 |
} |
} |
215 |
|
|
216 |
/** |
/** |
232 |
*/ |
*/ |
233 |
public int read(byte[] buf) throws IOException |
public int read(byte[] buf) throws IOException |
234 |
{ |
{ |
235 |
return(read(buf, 0, buf.length)); |
return read(buf, 0, buf.length); |
236 |
} |
} |
237 |
|
|
238 |
/** |
/** |
256 |
*/ |
*/ |
257 |
public int read(byte[] buf, int offset, int len) throws IOException |
public int read(byte[] buf, int offset, int len) throws IOException |
258 |
{ |
{ |
259 |
return(fd.read(buf, offset, len)); |
if (off < 0 || len < 0 || off + len > b.length) |
260 |
|
throw new ArrayIndexOutOfBoundsException(); |
261 |
|
|
262 |
|
return fd.read(buf, offset, len); |
263 |
} |
} |
264 |
|
|
265 |
/** |
/** |
266 |
* This method closes the stream. Any futher attempts to read from the |
* This method skips the specified number of bytes in the stream. It |
267 |
* stream will likely generate an IOException since the underlying file |
* returns the actual number of bytes skipped, which may be less than the |
268 |
* will be closed. |
* requested amount. |
269 |
|
* <p> |
270 |
|
* @param numBytes The requested number of bytes to skip |
271 |
* |
* |
272 |
* @exception IOException If an error occurs. |
* @return The actual number of bytes skipped. |
273 |
|
* |
274 |
|
* @exception IOException If an error occurs |
275 |
*/ |
*/ |
276 |
public void close() throws IOException |
public synchronized long skip(long numBytes) throws IOException |
277 |
{ |
{ |
278 |
fd.close(); |
if (numBytes < 0) |
279 |
|
throw new IllegalArgumentException("Can't skip negative bytes: " + |
280 |
|
numBytes); |
281 |
|
|
282 |
|
if (numBytes == 0) |
283 |
|
return(0); |
284 |
|
|
285 |
|
long curPos = fd.getFilePointer(); |
286 |
|
long newPos = fd.seek(numBytes, fd.CUR, true); |
287 |
|
|
288 |
|
return(newPos-curPos); |
289 |
} |
} |
290 |
|
|
291 |
/** |
/** |
294 |
* A file channel must be created by first creating an instance of |
* A file channel must be created by first creating an instance of |
295 |
* Input/Output/RandomAccessFile and invoking the getChannel() method on it. |
* Input/Output/RandomAccessFile and invoking the getChannel() method on it. |
296 |
*/ |
*/ |
297 |
public FileChannel getChannel() |
public synchronized FileChannel getChannel () |
298 |
{ |
{ |
299 |
synchronized (this) |
if (ch == null) |
300 |
{ |
ch = new FileChannelImpl ((int) (fd.getNativeFd () & 0xFFFF), this); |
|
// FIXME: Convert NIO to 64 bit |
|
|
if (ch == null) |
|
|
ch = new FileChannelImpl ((int) (fd.getNativeFd () & 0xFFFF), this); |
|
|
} |
|
301 |
|
|
302 |
return ch; |
return ch; |
303 |
} |
} |