39 * <code>FileReader</code>. 40 * 41 * @author Arthur van Hoff 42 * @see java.io.File 43 * @see java.io.FileDescriptor 44 * @see java.io.FileOutputStream 45 * @see java.nio.file.Files#newInputStream 46 * @since JDK1.0 47 */ 48 public 49 class FileInputStream extends InputStream 50 { 51 /* File Descriptor - handle to the open file */ 52 private final FileDescriptor fd; 53 54 private FileChannel channel = null; 55 56 private final Object closeLock = new Object(); 57 private volatile boolean closed = false; 58 59 /** 60 * Creates a <code>FileInputStream</code> by 61 * opening a connection to an actual file, 62 * the file named by the path name <code>name</code> 63 * in the file system. A new <code>FileDescriptor</code> 64 * object is created to represent this file 65 * connection. 66 * <p> 67 * First, if there is a security 68 * manager, its <code>checkRead</code> method 69 * is called with the <code>name</code> argument 70 * as its argument. 71 * <p> 72 * If the named file does not exist, is a directory rather than a regular 73 * file, or for some other reason cannot be opened for reading then a 74 * <code>FileNotFoundException</code> is thrown. 75 * 76 * @param name the system-dependent file name. 77 * @exception FileNotFoundException if the file does not exist, 78 * is a directory rather than a regular file, 107 * @param file the file to be opened for reading. 108 * @exception FileNotFoundException if the file does not exist, 109 * is a directory rather than a regular file, 110 * or for some other reason cannot be opened for 111 * reading. 112 * @exception SecurityException if a security manager exists and its 113 * <code>checkRead</code> method denies read access to the file. 114 * @see java.io.File#getPath() 115 * @see java.lang.SecurityManager#checkRead(java.lang.String) 116 */ 117 public FileInputStream(File file) throws FileNotFoundException { 118 String name = (file != null ? file.getPath() : null); 119 SecurityManager security = System.getSecurityManager(); 120 if (security != null) { 121 security.checkRead(name); 122 } 123 if (name == null) { 124 throw new NullPointerException(); 125 } 126 fd = new FileDescriptor(); 127 fd.attach(this); 128 open(name); 129 } 130 131 /** 132 * Creates a <code>FileInputStream</code> by using the file descriptor 133 * <code>fdObj</code>, which represents an existing connection to an 134 * actual file in the file system. 135 * <p> 136 * If there is a security manager, its <code>checkRead</code> method is 137 * called with the file descriptor <code>fdObj</code> as its argument to 138 * see if it's ok to read the file descriptor. If read access is denied 139 * to the file descriptor a <code>SecurityException</code> is thrown. 140 * <p> 141 * If <code>fdObj</code> is null then a <code>NullPointerException</code> 142 * is thrown. 143 * <p> 144 * This constructor does not throw an exception if <code>fdObj</code> 145 * is {@link java.io.FileDescriptor#valid() invalid}. 146 * However, if the methods are invoked on the resulting stream to attempt 147 * I/O on the stream, an <code>IOException</code> is thrown. 148 * 149 * @param fdObj the file descriptor to be opened for reading. 150 * @throws SecurityException if a security manager exists and its 151 * <code>checkRead</code> method denies read access to the 152 * file descriptor. 153 * @see SecurityManager#checkRead(java.io.FileDescriptor) 154 */ 155 public FileInputStream(FileDescriptor fdObj) { 156 SecurityManager security = System.getSecurityManager(); 157 if (fdObj == null) { 158 throw new NullPointerException(); 159 } 160 if (security != null) { 161 security.checkRead(fdObj); 162 } 163 fd = fdObj; 164 165 /* 166 * FileDescriptor is being shared by streams. 167 * Register this stream with FileDescriptor tracker. 168 */ 169 fd.attach(this); 170 } 171 172 /** 173 * Opens the specified file for reading. 174 * @param name the name of the file 175 */ 176 private native void open(String name) throws FileNotFoundException; 177 178 /** 179 * Reads a byte of data from this input stream. This method blocks 180 * if no input is yet available. 181 * 182 * @return the next byte of data, or <code>-1</code> if the end of the 183 * file is reached. 184 * @exception IOException if an I/O error occurs. 185 */ 186 public native int read() throws IOException; 187 188 /** 189 * Reads a subarray as a sequence of bytes. 276 /** 277 * Closes this file input stream and releases any system resources 278 * associated with the stream. 279 * 280 * <p> If this stream has an associated channel then the channel is closed 281 * as well. 282 * 283 * @exception IOException if an I/O error occurs. 284 * 285 * @revised 1.4 286 * @spec JSR-51 287 */ 288 public void close() throws IOException { 289 synchronized (closeLock) { 290 if (closed) { 291 return; 292 } 293 closed = true; 294 } 295 if (channel != null) { 296 channel.close(); 297 } 298 fd.closeAll(new Closeable() { 299 public void close() throws IOException { 300 close0(); 301 } 302 }); 303 } 304 305 /** 306 * Returns the <code>FileDescriptor</code> 307 * object that represents the connection to 308 * the actual file in the file system being 309 * used by this <code>FileInputStream</code>. 310 * 311 * @return the file descriptor object associated with this stream. 312 * @exception IOException if an I/O error occurs. 313 * @see java.io.FileDescriptor 314 */ 315 public final FileDescriptor getFD() throws IOException { 316 if (fd != null) { 317 return fd; 318 } 319 throw new IOException(); 320 } 321 322 /** 323 * Returns the unique {@link java.nio.channels.FileChannel FileChannel} 324 * object associated with this file input stream. 325 * 326 * <p> The initial {@link java.nio.channels.FileChannel#position() 327 * </code>position<code>} of the returned channel will be equal to the 328 * number of bytes read from the file so far. Reading bytes from this 329 * stream will increment the channel's position. Changing the channel's 330 * position, either explicitly or by reading, will change this stream's 331 * file position. 332 * 333 * @return the file channel associated with this file input stream 334 * 335 * @since 1.4 336 * @spec JSR-51 337 */ 338 public FileChannel getChannel() { 339 synchronized (this) { 340 if (channel == null) { 341 channel = FileChannelImpl.open(fd, true, false, this); 342 } 343 return channel; 344 } 345 } 346 347 private static native void initIDs(); 348 349 private native void close0() throws IOException; 350 351 static { 352 initIDs(); 353 } 354 355 /** 356 * Ensures that the <code>close</code> method of this file input stream is 357 * called when there are no more references to it. 358 * 359 * @exception IOException if an I/O error occurs. 360 * @see java.io.FileInputStream#close() 361 */ 362 protected void finalize() throws IOException { 363 if ((fd != null) && (fd != FileDescriptor.in)) { 364 /* if fd is shared, the references in FileDescriptor 365 * will ensure that finalizer is only called when 366 * safe to do so. All references using the fd have 367 * become unreachable. We can call close() 368 */ 369 close(); 370 } 371 } 372 } | 39 * <code>FileReader</code>. 40 * 41 * @author Arthur van Hoff 42 * @see java.io.File 43 * @see java.io.FileDescriptor 44 * @see java.io.FileOutputStream 45 * @see java.nio.file.Files#newInputStream 46 * @since JDK1.0 47 */ 48 public 49 class FileInputStream extends InputStream 50 { 51 /* File Descriptor - handle to the open file */ 52 private final FileDescriptor fd; 53 54 private FileChannel channel = null; 55 56 private final Object closeLock = new Object(); 57 private volatile boolean closed = false; 58 59 private static final ThreadLocal<Boolean> runningFinalize = 60 new ThreadLocal<>(); 61 62 private static boolean isRunningFinalize() { 63 Boolean val; 64 if ((val = runningFinalize.get()) != null) 65 return val.booleanValue(); 66 return false; 67 } 68 69 /** 70 * Creates a <code>FileInputStream</code> by 71 * opening a connection to an actual file, 72 * the file named by the path name <code>name</code> 73 * in the file system. A new <code>FileDescriptor</code> 74 * object is created to represent this file 75 * connection. 76 * <p> 77 * First, if there is a security 78 * manager, its <code>checkRead</code> method 79 * is called with the <code>name</code> argument 80 * as its argument. 81 * <p> 82 * If the named file does not exist, is a directory rather than a regular 83 * file, or for some other reason cannot be opened for reading then a 84 * <code>FileNotFoundException</code> is thrown. 85 * 86 * @param name the system-dependent file name. 87 * @exception FileNotFoundException if the file does not exist, 88 * is a directory rather than a regular file, 117 * @param file the file to be opened for reading. 118 * @exception FileNotFoundException if the file does not exist, 119 * is a directory rather than a regular file, 120 * or for some other reason cannot be opened for 121 * reading. 122 * @exception SecurityException if a security manager exists and its 123 * <code>checkRead</code> method denies read access to the file. 124 * @see java.io.File#getPath() 125 * @see java.lang.SecurityManager#checkRead(java.lang.String) 126 */ 127 public FileInputStream(File file) throws FileNotFoundException { 128 String name = (file != null ? file.getPath() : null); 129 SecurityManager security = System.getSecurityManager(); 130 if (security != null) { 131 security.checkRead(name); 132 } 133 if (name == null) { 134 throw new NullPointerException(); 135 } 136 fd = new FileDescriptor(); 137 fd.incrementAndGetUseCount(); 138 open(name); 139 } 140 141 /** 142 * Creates a <code>FileInputStream</code> by using the file descriptor 143 * <code>fdObj</code>, which represents an existing connection to an 144 * actual file in the file system. 145 * <p> 146 * If there is a security manager, its <code>checkRead</code> method is 147 * called with the file descriptor <code>fdObj</code> as its argument to 148 * see if it's ok to read the file descriptor. If read access is denied 149 * to the file descriptor a <code>SecurityException</code> is thrown. 150 * <p> 151 * If <code>fdObj</code> is null then a <code>NullPointerException</code> 152 * is thrown. 153 * <p> 154 * This constructor does not throw an exception if <code>fdObj</code> 155 * is {@link java.io.FileDescriptor#valid() invalid}. 156 * However, if the methods are invoked on the resulting stream to attempt 157 * I/O on the stream, an <code>IOException</code> is thrown. 158 * 159 * @param fdObj the file descriptor to be opened for reading. 160 * @throws SecurityException if a security manager exists and its 161 * <code>checkRead</code> method denies read access to the 162 * file descriptor. 163 * @see SecurityManager#checkRead(java.io.FileDescriptor) 164 */ 165 public FileInputStream(FileDescriptor fdObj) { 166 SecurityManager security = System.getSecurityManager(); 167 if (fdObj == null) { 168 throw new NullPointerException(); 169 } 170 if (security != null) { 171 security.checkRead(fdObj); 172 } 173 fd = fdObj; 174 175 /* 176 * FileDescriptor is being shared by streams. 177 * Ensure that it's GC'ed only when all the streams/channels are done 178 * using it. 179 */ 180 fd.incrementAndGetUseCount(); 181 } 182 183 /** 184 * Opens the specified file for reading. 185 * @param name the name of the file 186 */ 187 private native void open(String name) throws FileNotFoundException; 188 189 /** 190 * Reads a byte of data from this input stream. This method blocks 191 * if no input is yet available. 192 * 193 * @return the next byte of data, or <code>-1</code> if the end of the 194 * file is reached. 195 * @exception IOException if an I/O error occurs. 196 */ 197 public native int read() throws IOException; 198 199 /** 200 * Reads a subarray as a sequence of bytes. 287 /** 288 * Closes this file input stream and releases any system resources 289 * associated with the stream. 290 * 291 * <p> If this stream has an associated channel then the channel is closed 292 * as well. 293 * 294 * @exception IOException if an I/O error occurs. 295 * 296 * @revised 1.4 297 * @spec JSR-51 298 */ 299 public void close() throws IOException { 300 synchronized (closeLock) { 301 if (closed) { 302 return; 303 } 304 closed = true; 305 } 306 if (channel != null) { 307 /* 308 * Decrement the FD use count associated with the channel 309 * The use count is incremented whenever a new channel 310 * is obtained from this stream. 311 */ 312 fd.decrementAndGetUseCount(); 313 channel.close(); 314 } 315 316 /* 317 * Decrement the FD use count associated with this stream 318 */ 319 int useCount = fd.decrementAndGetUseCount(); 320 321 /* 322 * If FileDescriptor is still in use by another stream, the finalizer 323 * will not close it. 324 */ 325 if ((useCount <= 0) || !isRunningFinalize()) { 326 close0(); 327 } 328 } 329 330 /** 331 * Returns the <code>FileDescriptor</code> 332 * object that represents the connection to 333 * the actual file in the file system being 334 * used by this <code>FileInputStream</code>. 335 * 336 * @return the file descriptor object associated with this stream. 337 * @exception IOException if an I/O error occurs. 338 * @see java.io.FileDescriptor 339 */ 340 public final FileDescriptor getFD() throws IOException { 341 if (fd != null) return fd; 342 throw new IOException(); 343 } 344 345 /** 346 * Returns the unique {@link java.nio.channels.FileChannel FileChannel} 347 * object associated with this file input stream. 348 * 349 * <p> The initial {@link java.nio.channels.FileChannel#position() 350 * </code>position<code>} of the returned channel will be equal to the 351 * number of bytes read from the file so far. Reading bytes from this 352 * stream will increment the channel's position. Changing the channel's 353 * position, either explicitly or by reading, will change this stream's 354 * file position. 355 * 356 * @return the file channel associated with this file input stream 357 * 358 * @since 1.4 359 * @spec JSR-51 360 */ 361 public FileChannel getChannel() { 362 synchronized (this) { 363 if (channel == null) { 364 channel = FileChannelImpl.open(fd, true, false, this); 365 366 /* 367 * Increment fd's use count. Invoking the channel's close() 368 * method will result in decrementing the use count set for 369 * the channel. 370 */ 371 fd.incrementAndGetUseCount(); 372 } 373 return channel; 374 } 375 } 376 377 private static native void initIDs(); 378 379 private native void close0() throws IOException; 380 381 static { 382 initIDs(); 383 } 384 385 /** 386 * Ensures that the <code>close</code> method of this file input stream is 387 * called when there are no more references to it. 388 * 389 * @exception IOException if an I/O error occurs. 390 * @see java.io.FileInputStream#close() 391 */ 392 protected void finalize() throws IOException { 393 if ((fd != null) && (fd != FileDescriptor.in)) { 394 395 /* 396 * Finalizer should not release the FileDescriptor if another 397 * stream is still using it. If the user directly invokes 398 * close() then the FileDescriptor is also released. 399 */ 400 runningFinalize.set(Boolean.TRUE); 401 try { 402 close(); 403 } finally { 404 runningFinalize.set(Boolean.FALSE); 405 } 406 } 407 } 408 } |