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