FileInputStream.java revision 34625fce1396e8639a650af8905a579f9cf659a2
1/* 2 * Copyright (c) 1994, 2013, 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 26package java.io; 27 28import java.nio.channels.FileChannel; 29import sun.nio.ch.FileChannelImpl; 30import sun.misc.IoTrace; 31 32 33/** 34 * A <code>FileInputStream</code> obtains input bytes 35 * from a file in a file system. What files 36 * are available depends on the host environment. 37 * 38 * <p><code>FileInputStream</code> is meant for reading streams of raw bytes 39 * such as image data. For reading streams of characters, consider using 40 * <code>FileReader</code>. 41 * 42 * @author Arthur van Hoff 43 * @see java.io.File 44 * @see java.io.FileDescriptor 45 * @see java.io.FileOutputStream 46 * @see java.nio.file.Files#newInputStream 47 * @since JDK1.0 48 */ 49public 50class FileInputStream extends InputStream 51{ 52 /* File Descriptor - handle to the open file */ 53 private final FileDescriptor fd; 54 55 /* The path of the referenced file (null if the stream is created with a file descriptor) */ 56 private final String path; 57 58 private FileChannel channel = null; 59 60 private final Object closeLock = new Object(); 61 private volatile boolean closed = false; 62 63 private static final ThreadLocal<Boolean> runningFinalize = 64 new ThreadLocal<>(); 65 66 private static boolean isRunningFinalize() { 67 Boolean val; 68 if ((val = runningFinalize.get()) != null) 69 return val.booleanValue(); 70 return false; 71 } 72 73 /** 74 * Creates a <code>FileInputStream</code> by 75 * opening a connection to an actual file, 76 * the file named by the path name <code>name</code> 77 * in the file system. A new <code>FileDescriptor</code> 78 * object is created to represent this file 79 * connection. 80 * <p> 81 * First, if there is a security 82 * manager, its <code>checkRead</code> method 83 * is called with the <code>name</code> argument 84 * as its argument. 85 * <p> 86 * If the named file does not exist, is a directory rather than a regular 87 * file, or for some other reason cannot be opened for reading then a 88 * <code>FileNotFoundException</code> is thrown. 89 * 90 * @param name the system-dependent file name. 91 * @exception FileNotFoundException if the file does not exist, 92 * is a directory rather than a regular file, 93 * or for some other reason cannot be opened for 94 * reading. 95 * @exception SecurityException if a security manager exists and its 96 * <code>checkRead</code> method denies read access 97 * to the file. 98 * @see java.lang.SecurityManager#checkRead(java.lang.String) 99 */ 100 public FileInputStream(String name) throws FileNotFoundException { 101 this(name != null ? new File(name) : null); 102 } 103 104 /** 105 * Creates a <code>FileInputStream</code> by 106 * opening a connection to an actual file, 107 * the file named by the <code>File</code> 108 * object <code>file</code> in the file system. 109 * A new <code>FileDescriptor</code> object 110 * is created to represent this file connection. 111 * <p> 112 * First, if there is a security manager, 113 * its <code>checkRead</code> method is called 114 * with the path represented by the <code>file</code> 115 * argument as its argument. 116 * <p> 117 * If the named file does not exist, is a directory rather than a regular 118 * file, or for some other reason cannot be opened for reading then a 119 * <code>FileNotFoundException</code> is thrown. 120 * 121 * @param file the file to be opened for reading. 122 * @exception FileNotFoundException if the file does not exist, 123 * is a directory rather than a regular file, 124 * or for some other reason cannot be opened for 125 * reading. 126 * @exception SecurityException if a security manager exists and its 127 * <code>checkRead</code> method denies read access to the file. 128 * @see java.io.File#getPath() 129 * @see java.lang.SecurityManager#checkRead(java.lang.String) 130 */ 131 public FileInputStream(File file) throws FileNotFoundException { 132 String name = (file != null ? file.getPath() : null); 133 SecurityManager security = System.getSecurityManager(); 134 if (security != null) { 135 security.checkRead(name); 136 } 137 if (name == null) { 138 throw new NullPointerException(); 139 } 140 if (file.isInvalid()) { 141 throw new FileNotFoundException("Invalid file path"); 142 } 143 fd = new FileDescriptor(); 144 fd.incrementAndGetUseCount(); 145 this.path = name; 146 open(name); 147 } 148 149 /** 150 * Creates a <code>FileInputStream</code> by using the file descriptor 151 * <code>fdObj</code>, which represents an existing connection to an 152 * actual file in the file system. 153 * <p> 154 * If there is a security manager, its <code>checkRead</code> method is 155 * called with the file descriptor <code>fdObj</code> as its argument to 156 * see if it's ok to read the file descriptor. If read access is denied 157 * to the file descriptor a <code>SecurityException</code> is thrown. 158 * <p> 159 * If <code>fdObj</code> is null then a <code>NullPointerException</code> 160 * is thrown. 161 * <p> 162 * This constructor does not throw an exception if <code>fdObj</code> 163 * is {@link java.io.FileDescriptor#valid() invalid}. 164 * However, if the methods are invoked on the resulting stream to attempt 165 * I/O on the stream, an <code>IOException</code> is thrown. 166 * 167 * @param fdObj the file descriptor to be opened for reading. 168 * @throws SecurityException if a security manager exists and its 169 * <code>checkRead</code> method denies read access to the 170 * file descriptor. 171 * @see SecurityManager#checkRead(java.io.FileDescriptor) 172 */ 173 public FileInputStream(FileDescriptor fdObj) { 174 SecurityManager security = System.getSecurityManager(); 175 if (fdObj == null) { 176 throw new NullPointerException(); 177 } 178 if (security != null) { 179 security.checkRead(fdObj); 180 } 181 fd = fdObj; 182 path = null; 183 184 /* 185 * FileDescriptor is being shared by streams. 186 * Ensure that it's GC'ed only when all the streams/channels are done 187 * using it. 188 */ 189 fd.incrementAndGetUseCount(); 190 } 191 192 /** 193 * Opens the specified file for reading. 194 * @param name the name of the file 195 */ 196 private native void open(String name) throws FileNotFoundException; 197 198 /** 199 * Reads a byte of data from this input stream. This method blocks 200 * if no input is yet available. 201 * 202 * @return the next byte of data, or <code>-1</code> if the end of the 203 * file is reached. 204 * @exception IOException if an I/O error occurs. 205 */ 206 public int read() throws IOException { 207 Object traceContext = IoTrace.fileReadBegin(path); 208 int b = 0; 209 try { 210 b = read0(); 211 } finally { 212 IoTrace.fileReadEnd(traceContext, b == -1 ? 0 : 1); 213 } 214 return b; 215 } 216 217 private native int read0() throws IOException; 218 219 /** 220 * Reads a subarray as a sequence of bytes. 221 * @param b the data to be written 222 * @param off the start offset in the data 223 * @param len the number of bytes that are written 224 * @exception IOException If an I/O error has occurred. 225 */ 226 private native int readBytes(byte b[], int off, int len) throws IOException; 227 228 /** 229 * Reads up to <code>b.length</code> bytes of data from this input 230 * stream into an array of bytes. This method blocks until some input 231 * is available. 232 * 233 * @param b the buffer into which the data is read. 234 * @return the total number of bytes read into the buffer, or 235 * <code>-1</code> if there is no more data because the end of 236 * the file has been reached. 237 * @exception IOException if an I/O error occurs. 238 */ 239 public int read(byte b[]) throws IOException { 240 Object traceContext = IoTrace.fileReadBegin(path); 241 int bytesRead = 0; 242 try { 243 bytesRead = readBytes(b, 0, b.length); 244 } finally { 245 IoTrace.fileReadEnd(traceContext, bytesRead == -1 ? 0 : bytesRead); 246 } 247 return bytesRead; 248 } 249 250 /** 251 * Reads up to <code>len</code> bytes of data from this input stream 252 * into an array of bytes. If <code>len</code> is not zero, the method 253 * blocks until some input is available; otherwise, no 254 * bytes are read and <code>0</code> is returned. 255 * 256 * @param b the buffer into which the data is read. 257 * @param off the start offset in the destination array <code>b</code> 258 * @param len the maximum number of bytes read. 259 * @return the total number of bytes read into the buffer, or 260 * <code>-1</code> if there is no more data because the end of 261 * the file has been reached. 262 * @exception NullPointerException If <code>b</code> is <code>null</code>. 263 * @exception IndexOutOfBoundsException If <code>off</code> is negative, 264 * <code>len</code> is negative, or <code>len</code> is greater than 265 * <code>b.length - off</code> 266 * @exception IOException if an I/O error occurs. 267 */ 268 public int read(byte b[], int off, int len) throws IOException { 269 Object traceContext = IoTrace.fileReadBegin(path); 270 int bytesRead = 0; 271 try { 272 bytesRead = readBytes(b, off, len); 273 } finally { 274 IoTrace.fileReadEnd(traceContext, bytesRead == -1 ? 0 : bytesRead); 275 } 276 return bytesRead; 277 } 278 279 /** 280 * Skips over and discards <code>n</code> bytes of data from the 281 * input stream. 282 * 283 * <p>The <code>skip</code> method may, for a variety of 284 * reasons, end up skipping over some smaller number of bytes, 285 * possibly <code>0</code>. If <code>n</code> is negative, an 286 * <code>IOException</code> is thrown, even though the <code>skip</code> 287 * method of the {@link InputStream} superclass does nothing in this case. 288 * The actual number of bytes skipped is returned. 289 * 290 * <p>This method may skip more bytes than are remaining in the backing 291 * file. This produces no exception and the number of bytes skipped 292 * may include some number of bytes that were beyond the EOF of the 293 * backing file. Attempting to read from the stream after skipping past 294 * the end will result in -1 indicating the end of the file. 295 * 296 * @param n the number of bytes to be skipped. 297 * @return the actual number of bytes skipped. 298 * @exception IOException if n is negative, if the stream does not 299 * support seek, or if an I/O error occurs. 300 */ 301 public long skip(long n) throws IOException { 302 try { 303 return skip0(n); 304 } catch(UseManualSkipException e) { 305 return super.skip(n); 306 } 307 } 308 309 private native long skip0(long n) throws IOException, UseManualSkipException; 310 311 /* 312 * Used to force manual skip when FileInputStream operates on pipe 313 */ 314 private static class UseManualSkipException extends Exception { 315 } 316 317 /** 318 * Returns an estimate of the number of remaining bytes that can be read (or 319 * skipped over) from this input stream without blocking by the next 320 * invocation of a method for this input stream. The next invocation might be 321 * the same thread or another thread. A single read or skip of this 322 * many bytes will not block, but may read or skip fewer bytes. 323 * 324 * <p> In some cases, a non-blocking read (or skip) may appear to be 325 * blocked when it is merely slow, for example when reading large 326 * files over slow networks. 327 * 328 * @return an estimate of the number of remaining bytes that can be read 329 * (or skipped over) from this input stream without blocking. 330 * @exception IOException if this file input stream has been closed by calling 331 * {@code close} or an I/O error occurs. 332 */ 333 public native int available() 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 * @exception IOException if an I/O error occurs. 343 * 344 * @revised 1.4 345 * @spec JSR-51 346 */ 347 public void close() throws IOException { 348 synchronized (closeLock) { 349 if (closed) { 350 return; 351 } 352 closed = true; 353 } 354 if (channel != null) { 355 /* 356 * Decrement the FD use count associated with the channel 357 * The use count is incremented whenever a new channel 358 * is obtained from this stream. 359 */ 360 fd.decrementAndGetUseCount(); 361 channel.close(); 362 } 363 364 /* 365 * Decrement the FD use count associated with this stream 366 */ 367 int useCount = fd.decrementAndGetUseCount(); 368 369 /* 370 * If FileDescriptor is still in use by another stream, the finalizer 371 * will not close it. 372 */ 373 // Android change, make sure only last close closes FD. 374 if ((useCount <= 0)) // || !isRunningFinalize()) { 375 close0(); 376 } 377 } 378 379 /** 380 * Returns the <code>FileDescriptor</code> 381 * object that represents the connection to 382 * the actual file in the file system being 383 * used by this <code>FileInputStream</code>. 384 * 385 * @return the file descriptor object associated with this stream. 386 * @exception IOException if an I/O error occurs. 387 * @see java.io.FileDescriptor 388 */ 389 public final FileDescriptor getFD() throws IOException { 390 if (fd != null) return fd; 391 throw new IOException(); 392 } 393 394 /** 395 * Returns the unique {@link java.nio.channels.FileChannel FileChannel} 396 * object associated with this file input stream. 397 * 398 * <p> The initial {@link java.nio.channels.FileChannel#position() 399 * </code>position<code>} of the returned channel will be equal to the 400 * number of bytes read from the file so far. Reading bytes from this 401 * stream will increment the channel's position. Changing the channel's 402 * position, either explicitly or by reading, will change this stream's 403 * file position. 404 * 405 * @return the file channel associated with this file input stream 406 * 407 * @since 1.4 408 * @spec JSR-51 409 */ 410 public FileChannel getChannel() { 411 synchronized (this) { 412 if (channel == null) { 413 channel = FileChannelImpl.open(fd, path, true, false, this); 414 415 /* 416 * Increment fd's use count. Invoking the channel's close() 417 * method will result in decrementing the use count set for 418 * the channel. 419 */ 420 fd.incrementAndGetUseCount(); 421 } 422 return channel; 423 } 424 } 425 426 private static native void initIDs(); 427 428 private native void close0() throws IOException; 429 430 static { 431 initIDs(); 432 } 433 434 /** 435 * Ensures that the <code>close</code> method of this file input stream is 436 * called when there are no more references to it. 437 * 438 * @exception IOException if an I/O error occurs. 439 * @see java.io.FileInputStream#close() 440 */ 441 protected void finalize() throws IOException { 442 if ((fd != null) && (fd != FileDescriptor.in)) { 443 444 /* 445 * Finalizer should not release the FileDescriptor if another 446 * stream is still using it. If the user directly invokes 447 * close() then the FileDescriptor is also released. 448 */ 449 runningFinalize.set(Boolean.TRUE); 450 try { 451 close(); 452 } finally { 453 runningFinalize.set(Boolean.FALSE); 454 } 455 } 456 } 457} 458