1 /* 2 * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.io; 27 28 import java.nio.channels.FileChannel; 29 import sun.nio.ch.FileChannelImpl; 30 31 32 /** 33 * A <code>FileInputStream</code> obtains input bytes 34 * from a file in a file system. What files 35 * are available depends on the host environment. 36 * 37 * <p><code>FileInputStream</code> is meant for reading streams of raw bytes 38 * such as image data. For reading streams of characters, consider using 39 * <code>FileReader</code>. 40 * 41 * @apiNote 42 * To release resources used by this stream {@link #close} should be called 43 * directly or by try-with-resources. Subclasses are responsible for the cleanup 44 * of resources acquired by the subclass. 45 * Subclasses that override {@link #finalize} in order to perform cleanup 46 * should be modified to use alternative cleanup mechanisms such as 47 * {@link java.lang.ref.Cleaner} and remove the overriding {@code finalize} method. 48 * 49 * @implSpec 50 * If this FileInputStream has been subclassed and the {@link #close} 51 * method has been overridden, the {@link #close} method will be 52 * called when the FileInputStream is unreachable. 53 * Otherwise, it is implementation specific how the resource cleanup described in 54 * {@link #close} is performed. 55 56 * 57 * @author Arthur van Hoff 58 * @see java.io.File 59 * @see java.io.FileDescriptor 60 * @see java.io.FileOutputStream 61 * @see java.nio.file.Files#newInputStream 62 * @since 1.0 63 */ 64 public 65 class FileInputStream extends InputStream 66 { 67 /* File Descriptor - handle to the open file */ 68 private final FileDescriptor fd; 69 70 /** 71 * The path of the referenced file 72 * (null if the stream is created with a file descriptor) 73 */ 74 private final String path; 75 76 private volatile FileChannel channel; 77 78 private final Object closeLock = new Object(); 79 80 private volatile boolean closed; 81 82 private final Object altFinalizer; 83 84 /** 85 * Creates a <code>FileInputStream</code> by 86 * opening a connection to an actual file, 87 * the file named by the path name <code>name</code> 88 * in the file system. A new <code>FileDescriptor</code> 89 * object is created to represent this file 90 * connection. 91 * <p> 92 * First, if there is a security 93 * manager, its <code>checkRead</code> method 94 * is called with the <code>name</code> argument 95 * as its argument. 96 * <p> 97 * If the named file does not exist, is a directory rather than a regular 98 * file, or for some other reason cannot be opened for reading then a 99 * <code>FileNotFoundException</code> is thrown. 100 * 101 * @param name the system-dependent file name. 102 * @exception FileNotFoundException if the file does not exist, 103 * is a directory rather than a regular file, 104 * or for some other reason cannot be opened for 105 * reading. 106 * @exception SecurityException if a security manager exists and its 107 * <code>checkRead</code> method denies read access 108 * to the file. 109 * @see java.lang.SecurityManager#checkRead(java.lang.String) 110 */ 111 public FileInputStream(String name) throws FileNotFoundException { 112 this(name != null ? new File(name) : null); 113 } 114 115 /** 116 * Creates a <code>FileInputStream</code> by 117 * opening a connection to an actual file, 118 * the file named by the <code>File</code> 119 * object <code>file</code> in the file system. 120 * A new <code>FileDescriptor</code> object 121 * is created to represent this file connection. 122 * <p> 123 * First, if there is a security manager, 124 * its <code>checkRead</code> method is called 125 * with the path represented by the <code>file</code> 126 * argument as its argument. 127 * <p> 128 * If the named file does not exist, is a directory rather than a regular 129 * file, or for some other reason cannot be opened for reading then a 130 * <code>FileNotFoundException</code> is thrown. 131 * 132 * @param file the file to be opened for reading. 133 * @exception FileNotFoundException if the file does not exist, 134 * is a directory rather than a regular file, 135 * or for some other reason cannot be opened for 136 * reading. 137 * @exception SecurityException if a security manager exists and its 138 * <code>checkRead</code> method denies read access to the file. 139 * @see java.io.File#getPath() 140 * @see java.lang.SecurityManager#checkRead(java.lang.String) 141 */ 142 public FileInputStream(File file) throws FileNotFoundException { 143 String name = (file != null ? file.getPath() : null); 144 SecurityManager security = System.getSecurityManager(); 145 if (security != null) { 146 security.checkRead(name); 147 } 148 if (name == null) { 149 throw new NullPointerException(); 150 } 151 if (file.isInvalid()) { 152 throw new FileNotFoundException("Invalid file path"); 153 } 154 fd = new FileDescriptor(); 155 fd.attach(this); 156 path = name; 157 open(name); 158 altFinalizer = getFinalizer(this); 159 if (altFinalizer == null) { 160 FileCleanable.register(fd); // open set the fd, register the cleanup 161 } 162 } 163 164 /** 165 * Creates a <code>FileInputStream</code> by using the file descriptor 166 * <code>fdObj</code>, which represents an existing connection to an 167 * actual file in the file system. 168 * <p> 169 * If there is a security manager, its <code>checkRead</code> method is 170 * called with the file descriptor <code>fdObj</code> as its argument to 171 * see if it's ok to read the file descriptor. If read access is denied 172 * to the file descriptor a <code>SecurityException</code> is thrown. 173 * <p> 174 * If <code>fdObj</code> is null then a <code>NullPointerException</code> 175 * is thrown. 176 * <p> 177 * This constructor does not throw an exception if <code>fdObj</code> 178 * is {@link java.io.FileDescriptor#valid() invalid}. 179 * However, if the methods are invoked on the resulting stream to attempt 180 * I/O on the stream, an <code>IOException</code> is thrown. 181 * 182 * @param fdObj the file descriptor to be opened for reading. 183 * @throws SecurityException if a security manager exists and its 184 * <code>checkRead</code> method denies read access to the 185 * file descriptor. 186 * @see SecurityManager#checkRead(java.io.FileDescriptor) 187 */ 188 public FileInputStream(FileDescriptor fdObj) { 189 SecurityManager security = System.getSecurityManager(); 190 if (fdObj == null) { 191 throw new NullPointerException(); 192 } 193 if (security != null) { 194 security.checkRead(fdObj); 195 } 196 fd = fdObj; 197 path = null; 198 altFinalizer = null; 199 200 /* 201 * FileDescriptor is being shared by streams. 202 * Register this stream with FileDescriptor tracker. 203 */ 204 fd.attach(this); 205 } 206 207 /** 208 * Opens the specified file for reading. 209 * @param name the name of the file 210 */ 211 private native void open0(String name) throws FileNotFoundException; 212 213 // wrap native call to allow instrumentation 214 /** 215 * Opens the specified file for reading. 216 * @param name the name of the file 217 */ 218 private void open(String name) throws FileNotFoundException { 219 open0(name); 220 } 221 222 /** 223 * Reads a byte of data from this input stream. This method blocks 224 * if no input is yet available. 225 * 226 * @return the next byte of data, or <code>-1</code> if the end of the 227 * file is reached. 228 * @exception IOException if an I/O error occurs. 229 */ 230 public int read() throws IOException { 231 return read0(); 232 } 233 234 private native int read0() throws IOException; 235 236 /** 237 * Reads a subarray as a sequence of bytes. 238 * @param b the data to be written 239 * @param off the start offset in the data 240 * @param len the number of bytes that are written 241 * @exception IOException If an I/O error has occurred. 242 */ 243 private native int readBytes(byte b[], int off, int len) throws IOException; 244 245 /** 246 * Reads up to <code>b.length</code> bytes of data from this input 247 * stream into an array of bytes. This method blocks until some input 248 * is available. 249 * 250 * @param b the buffer into which the data is read. 251 * @return the total number of bytes read into the buffer, or 252 * <code>-1</code> if there is no more data because the end of 253 * the file has been reached. 254 * @exception IOException if an I/O error occurs. 255 */ 256 public int read(byte b[]) throws IOException { 257 return readBytes(b, 0, b.length); 258 } 259 260 /** 261 * Reads up to <code>len</code> bytes of data from this input stream 262 * into an array of bytes. If <code>len</code> is not zero, the method 263 * blocks until some input is available; otherwise, no 264 * bytes are read and <code>0</code> is returned. 265 * 266 * @param b the buffer into which the data is read. 267 * @param off the start offset in the destination array <code>b</code> 268 * @param len the maximum number of bytes read. 269 * @return the total number of bytes read into the buffer, or 270 * <code>-1</code> if there is no more data because the end of 271 * the file has been reached. 272 * @exception NullPointerException If <code>b</code> is <code>null</code>. 273 * @exception IndexOutOfBoundsException If <code>off</code> is negative, 274 * <code>len</code> is negative, or <code>len</code> is greater than 275 * <code>b.length - off</code> 276 * @exception IOException if an I/O error occurs. 277 */ 278 public int read(byte b[], int off, int len) throws IOException { 279 return readBytes(b, off, len); 280 } 281 282 /** 283 * Skips over and discards <code>n</code> bytes of data from the 284 * input stream. 285 * 286 * <p>The <code>skip</code> method may, for a variety of 287 * reasons, end up skipping over some smaller number of bytes, 288 * possibly <code>0</code>. If <code>n</code> is negative, the method 289 * will try to skip backwards. In case the backing file does not support 290 * backward skip at its current position, an <code>IOException</code> is 291 * thrown. The actual number of bytes skipped is returned. If it skips 292 * forwards, it returns a positive value. If it skips backwards, it 293 * returns a negative value. 294 * 295 * <p>This method may skip more bytes than what are remaining in the 296 * backing file. This produces no exception and the number of bytes skipped 297 * may include some number of bytes that were beyond the EOF of the 298 * backing file. Attempting to read from the stream after skipping past 299 * the end will result in -1 indicating the end of the file. 300 * 301 * @param n the number of bytes to be skipped. 302 * @return the actual number of bytes skipped. 303 * @exception IOException if n is negative, if the stream does not 304 * support seek, or if an I/O error occurs. 305 */ 306 public long skip(long n) throws IOException { 307 return skip0(n); 308 } 309 310 private native long skip0(long n) throws IOException; 311 312 /** 313 * Returns an estimate of the number of remaining bytes that can be read (or 314 * skipped over) from this input stream without blocking by the next 315 * invocation of a method for this input stream. Returns 0 when the file 316 * position is beyond EOF. The next invocation might be the same thread 317 * or another thread. A single read or skip of this many bytes will not 318 * block, but may read or skip fewer bytes. 319 * 320 * <p> In some cases, a non-blocking read (or skip) may appear to be 321 * blocked when it is merely slow, for example when reading large 322 * files over slow networks. 323 * 324 * @return an estimate of the number of remaining bytes that can be read 325 * (or skipped over) from this input stream without blocking. 326 * @exception IOException if this file input stream has been closed by calling 327 * {@code close} or an I/O error occurs. 328 */ 329 public int available() throws IOException { 330 return available0(); 331 } 332 333 private native int available0() throws IOException; 334 335 /** 336 * Closes this file input stream and releases any system resources 337 * associated with the stream. 338 * 339 * <p> If this stream has an associated channel then the channel is closed 340 * as well. 341 * 342 * @apiNote 343 * Overriding {@link #close} to perform cleanup actions is reliable 344 * only when called directly or when called by try-with-resources. 345 * Do not depend on finalization to invoke {@code close}; 346 * finalization is not reliable and is deprecated. 347 * If cleanup of native resources is needed, other mechanisms such as 348 * {@linkplain java.lang.ref.Cleaner} should be used. 349 * 350 * @exception IOException if an I/O error occurs. 351 * 352 * @revised 1.4 353 * @spec JSR-51 354 */ 355 public void close() throws IOException { 356 if (closed) { 357 return; 358 } 359 synchronized (closeLock) { 360 if (closed) { 361 return; 362 } 363 closed = true; 364 } 365 366 FileChannel fc = channel; 367 if (fc != null) { 368 // possible race with getChannel(), benign since 369 // FileChannel.close is final and idempotent 370 fc.close(); 371 } 372 373 fd.closeAll(new Closeable() { 374 public void close() throws IOException { 375 fd.close(); 376 } 377 }); 378 } 379 380 /** 381 * Returns the <code>FileDescriptor</code> 382 * object that represents the connection to 383 * the actual file in the file system being 384 * used by this <code>FileInputStream</code>. 385 * 386 * @return the file descriptor object associated with this stream. 387 * @exception IOException if an I/O error occurs. 388 * @see java.io.FileDescriptor 389 */ 390 public final FileDescriptor getFD() throws IOException { 391 if (fd != null) { 392 return fd; 393 } 394 throw new IOException(); 395 } 396 397 /** 398 * Returns the unique {@link java.nio.channels.FileChannel FileChannel} 399 * object associated with this file input stream. 400 * 401 * <p> The initial {@link java.nio.channels.FileChannel#position() 402 * position} of the returned channel will be equal to the 403 * number of bytes read from the file so far. Reading bytes from this 404 * stream will increment the channel's position. Changing the channel's 405 * position, either explicitly or by reading, will change this stream's 406 * file position. 407 * 408 * @return the file channel associated with this file input stream 409 * 410 * @since 1.4 411 * @spec JSR-51 412 */ 413 public FileChannel getChannel() { 414 FileChannel fc = this.channel; 415 if (fc == null) { 416 synchronized (this) { 417 fc = this.channel; 418 if (fc == null) { 419 this.channel = fc = FileChannelImpl.open(fd, path, true, 420 false, false, this); 421 if (closed) { 422 try { 423 // possible race with close(), benign since 424 // FileChannel.close is final and idempotent 425 fc.close(); 426 } catch (IOException ioe) { 427 throw new InternalError(ioe); // should not happen 428 } 429 } 430 } 431 } 432 } 433 return fc; 434 } 435 436 private static native void initIDs(); 437 438 static { 439 initIDs(); 440 } 441 442 /** 443 * Ensures that the {@link #close} method of this file input stream is 444 * called when there are no more references to it. 445 * The {@link #finalize} method does not call {@link #close} directly. 446 * 447 * @apiNote 448 * To release resources used by this stream {@link #close} should be called 449 * directly or by try-with-resources. 450 * 451 * @implSpec 452 * If this FileInputStream has been subclassed and the {@link #close} 453 * method has been overridden, the {@link #close} method will be 454 * called when the FileInputStream is unreachable. 455 * Otherwise, it is implementation specific how the resource cleanup described in 456 * {@link #close} is performed. 457 * 458 * @deprecated The {@code finalize} method has been deprecated and will be removed. 459 * Subclasses that override {@code finalize} in order to perform cleanup 460 * should be modified to use alternative cleanup mechanisms and 461 * to remove the overriding {@code finalize} method. 462 * When overriding the {@code finalize} method, its implementation must explicitly 463 * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}. 464 * See the specification for {@link Object#finalize()} for further 465 * information about migration options. 466 * 467 * @exception IOException if an I/O error occurs. 468 * @see java.io.FileInputStream#close() 469 */ 470 @Deprecated(since="9", forRemoval = true) 471 protected void finalize() throws IOException { 472 } 473 474 /* 475 * Returns a finalizer object if the FIS needs a finalizer; otherwise null. 476 * If the FIS has a close method; it needs an AltFinalizer. 477 */ 478 private static Object getFinalizer(FileInputStream fis) { 479 Class<?> clazz = fis.getClass(); 480 while (clazz != FileInputStream.class) { 481 try { 482 clazz.getDeclaredMethod("close"); 483 return new AltFinalizer(fis); 484 } catch (NoSuchMethodException nsme) { 485 // ignore 486 } 487 clazz = clazz.getSuperclass(); 488 } 489 return null; 490 } 491 /** 492 * Class to call {@code FileInputStream.close} when finalized. 493 * If finalization of the stream is needed, an instance is created 494 * in its constructor(s). When the set of instances 495 * related to the stream is unreachable, the AltFinalizer performs 496 * the needed call to the stream's {@code close} method. 497 */ 498 static class AltFinalizer { 499 private final FileInputStream fis; 500 501 AltFinalizer(FileInputStream fis) { 502 this.fis = fis; 503 } 504 505 @Override 506 @SuppressWarnings("deprecation") 507 protected final void finalize() { 508 try { 509 if ((fis.fd != null) && (fis.fd != FileDescriptor.in)) { 510 /* if fd is shared, the references in FileDescriptor 511 * will ensure that finalizer is only called when 512 * safe to do so. All references using the fd have 513 * become unreachable. We can call close() 514 */ 515 fis.close(); 516 } 517 } catch (IOException ioe) { 518 // ignore 519 } 520 } 521 } 522 }