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