• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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