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