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