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