1 /* 2 * Copyright (c) 1994, 2020, 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} 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} is meant for reading streams of raw bytes 38 * such as image data. For reading streams of characters, consider using 39 * {@code FileReader}. 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 * @author Arthur van Hoff 57 * @see java.io.File 58 * @see java.io.FileDescriptor 59 * @see java.io.FileOutputStream 60 * @see java.nio.file.Files#newInputStream 61 * @since 1.0 62 */ 63 public class FileInputStream extends InputStream 64 { 65 /* File Descriptor - handle to the open file */ 66 private final FileDescriptor fd; 67 68 /** 69 * The path of the referenced file 70 * (null if the stream is created with a file descriptor) 71 */ 72 private final String path; 73 74 private volatile FileChannel channel; 75 76 private final Object closeLock = new Object(); 77 78 private volatile boolean closed; 79 80 /** 81 * Creates a {@code FileInputStream} by 82 * opening a connection to an actual file, 83 * the file named by the path name {@code name} 84 * in the file system. A new {@code FileDescriptor} 85 * object is created to represent this file 86 * connection. 87 * <p> 88 * First, if there is a security 89 * manager, its {@code checkRead} method 90 * is called with the {@code name} argument 91 * as its argument. 92 * <p> 93 * If the named file does not exist, is a directory rather than a regular 94 * file, or for some other reason cannot be opened for reading then a 95 * {@code FileNotFoundException} is thrown. 96 * 97 * @param name the system-dependent file name. 98 * @throws FileNotFoundException if the file does not exist, 99 * is a directory rather than a regular file, 100 * or for some other reason cannot be opened for 101 * reading. 102 * @throws SecurityException if a security manager exists and its 103 * {@code checkRead} method denies read access 104 * to the file. 105 * @see java.lang.SecurityManager#checkRead(java.lang.String) 106 */ 107 public FileInputStream(String name) throws FileNotFoundException { 108 this(name != null ? new File(name) : null); 109 } 110 111 /** 112 * Creates a {@code FileInputStream} by 113 * opening a connection to an actual file, 114 * the file named by the {@code File} 115 * object {@code file} in the file system. 116 * A new {@code FileDescriptor} object 117 * is created to represent this file connection. 118 * <p> 119 * First, if there is a security manager, 120 * its {@code checkRead} method is called 121 * with the path represented by the {@code file} 122 * argument as its argument. 123 * <p> 124 * If the named file does not exist, is a directory rather than a regular 125 * file, or for some other reason cannot be opened for reading then a 126 * {@code FileNotFoundException} is thrown. 127 * 128 * @param file the file to be opened for reading. 129 * @throws FileNotFoundException if the file does not exist, 130 * is a directory rather than a regular file, 131 * or for some other reason cannot be opened for 132 * reading. 133 * @throws SecurityException if a security manager exists and its 134 * {@code checkRead} method denies read access to the file. 135 * @see java.io.File#getPath() 136 * @see java.lang.SecurityManager#checkRead(java.lang.String) 137 */ 138 public FileInputStream(File file) throws FileNotFoundException { 139 String name = (file != null ? file.getPath() : null); 140 SecurityManager security = System.getSecurityManager(); 141 if (security != null) { 142 security.checkRead(name); 143 } 144 if (name == null) { 145 throw new NullPointerException(); 146 } 147 if (file.isInvalid()) { 148 throw new FileNotFoundException("Invalid file path"); 149 } 150 fd = new FileDescriptor(); 151 fd.attach(this); 152 path = name; 153 open(name); 154 FileCleanable.register(fd); // open set the fd, register the cleanup 155 } 156 157 /** 158 * Creates a {@code FileInputStream} by using the file descriptor 159 * {@code fdObj}, which represents an existing connection to an 160 * actual file in the file system. 161 * <p> 162 * If there is a security manager, its {@code checkRead} method is 163 * called with the file descriptor {@code fdObj} as its argument to 164 * see if it's ok to read the file descriptor. If read access is denied 165 * to the file descriptor a {@code SecurityException} is thrown. 166 * <p> 167 * If {@code fdObj} is null then a {@code NullPointerException} 168 * is thrown. 169 * <p> 170 * This constructor does not throw an exception if {@code fdObj} 171 * is {@link java.io.FileDescriptor#valid() invalid}. 172 * However, if the methods are invoked on the resulting stream to attempt 173 * I/O on the stream, an {@code IOException} is thrown. 174 * 175 * @param fdObj the file descriptor to be opened for reading. 176 * @throws SecurityException if a security manager exists and its 177 * {@code checkRead} method denies read access to the 178 * file descriptor. 179 * @see SecurityManager#checkRead(java.io.FileDescriptor) 180 */ 181 public FileInputStream(FileDescriptor fdObj) { 182 SecurityManager security = System.getSecurityManager(); 183 if (fdObj == null) { 184 throw new NullPointerException(); 185 } 186 if (security != null) { 187 security.checkRead(fdObj); 188 } 189 fd = fdObj; 190 path = null; 191 192 /* 193 * FileDescriptor is being shared by streams. 194 * Register this stream with FileDescriptor tracker. 195 */ 196 fd.attach(this); 197 } 198 199 /** 200 * Opens the specified file for reading. 201 * @param name the name of the file 202 */ 203 private native void open0(String name) throws FileNotFoundException; 204 205 // wrap native call to allow instrumentation 206 /** 207 * Opens the specified file for reading. 208 * @param name the name of the file 209 */ 210 private void open(String name) throws FileNotFoundException { 211 open0(name); 212 } 213 214 /** 215 * Reads a byte of data from this input stream. This method blocks 216 * if no input is yet available. 217 * 218 * @return the next byte of data, or {@code -1} if the end of the 219 * file is reached. 220 * @throws IOException if an I/O error occurs. 221 */ 222 public int read() throws IOException { 223 return read0(); 224 } 225 226 private native int read0() throws IOException; 227 228 /** 229 * Reads a subarray as a sequence of bytes. 230 * @param b the data to be written 231 * @param off the start offset in the data 232 * @param len the number of bytes that are written 233 * @throws IOException If an I/O error has occurred. 234 */ 235 private native int readBytes(byte b[], int off, int len) throws IOException; 236 237 /** 238 * Reads up to {@code b.length} bytes of data from this input 239 * stream into an array of bytes. This method blocks until some input 240 * is available. 241 * 242 * @param b the buffer into which the data is read. 243 * @return the total number of bytes read into the buffer, or 244 * {@code -1} if there is no more data because the end of 245 * the file has been reached. 246 * @throws IOException if an I/O error occurs. 247 */ 248 public int read(byte b[]) throws IOException { 249 return readBytes(b, 0, b.length); 250 } 251 252 /** 253 * Reads up to {@code len} bytes of data from this input stream 254 * into an array of bytes. If {@code len} is not zero, the method 255 * blocks until some input is available; otherwise, no 256 * bytes are read and {@code 0} is returned. 257 * 258 * @param b the buffer into which the data is read. 259 * @param off the start offset in the destination array {@code b} 260 * @param len the maximum number of bytes read. 261 * @return the total number of bytes read into the buffer, or 262 * {@code -1} if there is no more data because the end of 263 * the file has been reached. 264 * @throws NullPointerException If {@code b} is {@code null}. 265 * @throws IndexOutOfBoundsException If {@code off} is negative, 266 * {@code len} is negative, or {@code len} is greater than 267 * {@code b.length - off} 268 * @throws IOException if an I/O error occurs. 269 */ 270 public int read(byte b[], int off, int len) throws IOException { 271 return readBytes(b, off, len); 272 } 273 274 /** 275 * Skips over and discards {@code n} bytes of data from the 276 * input stream. 277 * 278 * <p>The {@code skip} method may, for a variety of 279 * reasons, end up skipping over some smaller number of bytes, 280 * possibly {@code 0}. If {@code n} is negative, the method 281 * will try to skip backwards. In case the backing file does not support 282 * backward skip at its current position, an {@code IOException} is 283 * thrown. The actual number of bytes skipped is returned. If it skips 284 * forwards, it returns a positive value. If it skips backwards, it 285 * returns a negative value. 286 * 287 * <p>This method may skip more bytes than what are remaining in the 288 * backing file. This produces no exception and the number of bytes skipped 289 * may include some number of bytes that were beyond the EOF of the 290 * backing file. Attempting to read from the stream after skipping past 291 * the end will result in -1 indicating the end of the file. 292 * 293 * @param n the number of bytes to be skipped. 294 * @return the actual number of bytes skipped. 295 * @throws IOException if n is negative, if the stream does not 296 * support seek, or if an I/O error occurs. 297 */ 298 public long skip(long n) throws IOException { 299 return skip0(n); 300 } 301 302 private native long skip0(long n) throws IOException; 303 304 /** 305 * Returns an estimate of the number of remaining bytes that can be read (or 306 * skipped over) from this input stream without blocking by the next 307 * invocation of a method for this input stream. Returns 0 when the file 308 * position is beyond EOF. The next invocation might be the same thread 309 * or another thread. A single read or skip of this many bytes will not 310 * block, but may read or skip fewer bytes. 311 * 312 * <p> In some cases, a non-blocking read (or skip) may appear to be 313 * blocked when it is merely slow, for example when reading large 314 * files over slow networks. 315 * 316 * @return an estimate of the number of remaining bytes that can be read 317 * (or skipped over) from this input stream without blocking. 318 * @throws IOException if this file input stream has been closed by calling 319 * {@code close} or an I/O error occurs. 320 */ 321 public int available() throws IOException { 322 return available0(); 323 } 324 325 private native int available0() throws IOException; 326 327 /** 328 * Closes this file input stream and releases any system resources 329 * associated with the stream. 330 * 331 * <p> If this stream has an associated channel then the channel is closed 332 * as well. 333 * 334 * @apiNote 335 * Overriding {@link #close} to perform cleanup actions is reliable 336 * only when called directly or when called by try-with-resources. 337 * Do not depend on finalization to invoke {@code close}; 338 * finalization is not reliable and is deprecated. 339 * If cleanup of native resources is needed, other mechanisms such as 340 * {@linkplain java.lang.ref.Cleaner} should be used. 341 * 342 * @throws IOException if an I/O error occurs. 343 * 344 * @revised 1.4 345 * @spec JSR-51 346 */ 347 public void close() throws IOException { 348 if (closed) { 349 return; 350 } 351 synchronized (closeLock) { 352 if (closed) { 353 return; 354 } 355 closed = true; 356 } 357 358 FileChannel fc = channel; 359 if (fc != null) { 360 // possible race with getChannel(), benign since 361 // FileChannel.close is final and idempotent 362 fc.close(); 363 } 364 365 fd.closeAll(new Closeable() { 366 public void close() throws IOException { 367 fd.close(); 368 } 369 }); 370 } 371 372 /** 373 * Returns the {@code FileDescriptor} 374 * object that represents the connection to 375 * the actual file in the file system being 376 * used by this {@code FileInputStream}. 377 * 378 * @return the file descriptor object associated with this stream. 379 * @throws IOException if an I/O error occurs. 380 * @see java.io.FileDescriptor 381 */ 382 public final FileDescriptor getFD() throws IOException { 383 if (fd != null) { 384 return fd; 385 } 386 throw new IOException(); 387 } 388 389 /** 390 * Returns the unique {@link java.nio.channels.FileChannel FileChannel} 391 * object associated with this file input stream. 392 * 393 * <p> The initial {@link java.nio.channels.FileChannel#position() 394 * position} of the returned channel will be equal to the 395 * number of bytes read from the file so far. Reading bytes from this 396 * stream will increment the channel's position. Changing the channel's 397 * position, either explicitly or by reading, will change this stream's 398 * file position. 399 * 400 * @return the file channel associated with this file input stream 401 * 402 * @since 1.4 403 * @spec JSR-51 404 */ 405 public FileChannel getChannel() { 406 FileChannel fc = this.channel; 407 if (fc == null) { 408 synchronized (this) { 409 fc = this.channel; 410 if (fc == null) { 411 this.channel = fc = FileChannelImpl.open(fd, path, true, 412 false, false, this); 413 if (closed) { 414 try { 415 // possible race with close(), benign since 416 // FileChannel.close is final and idempotent 417 fc.close(); 418 } catch (IOException ioe) { 419 throw new InternalError(ioe); // should not happen 420 } 421 } 422 } 423 } 424 } 425 return fc; 426 } 427 428 private static native void initIDs(); 429 430 static { 431 initIDs(); 432 } 433 }