2
* Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.
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
28
import java.nio.channels.FileChannel;
29
import sun.nio.ch.FileChannelImpl;
33
* A <code>FileInputStream</code> obtains input bytes
34
* from a file in a file system. What files
35
* are available depends on the host environment.
37
* <p><code>FileInputStream</code> is meant for reading streams of raw bytes
38
* such as image data. For reading streams of characters, consider using
39
* <code>FileReader</code>.
41
* @author Arthur van Hoff
43
* @see java.io.FileDescriptor
44
* @see java.io.FileOutputStream
45
* @see java.nio.file.Files#newInputStream
49
class FileInputStream extends InputStream
51
/* File Descriptor - handle to the open file */
52
private final FileDescriptor fd;
54
private FileChannel channel = null;
56
private final Object closeLock = new Object();
57
private volatile boolean closed = false;
59
private static final ThreadLocal<Boolean> runningFinalize =
62
private static boolean isRunningFinalize() {
64
if ((val = runningFinalize.get()) != null)
65
return val.booleanValue();
70
* Creates a <code>FileInputStream</code> by
71
* opening a connection to an actual file,
72
* the file named by the path name <code>name</code>
73
* in the file system. A new <code>FileDescriptor</code>
74
* object is created to represent this file
77
* First, if there is a security
78
* manager, its <code>checkRead</code> method
79
* is called with the <code>name</code> argument
82
* If the named file does not exist, is a directory rather than a regular
83
* file, or for some other reason cannot be opened for reading then a
84
* <code>FileNotFoundException</code> is thrown.
86
* @param name the system-dependent file name.
87
* @exception FileNotFoundException if the file does not exist,
88
* is a directory rather than a regular file,
89
* or for some other reason cannot be opened for
91
* @exception SecurityException if a security manager exists and its
92
* <code>checkRead</code> method denies read access
94
* @see java.lang.SecurityManager#checkRead(java.lang.String)
96
public FileInputStream(String name) throws FileNotFoundException {
97
this(name != null ? new File(name) : null);
101
* Creates a <code>FileInputStream</code> by
102
* opening a connection to an actual file,
103
* the file named by the <code>File</code>
104
* object <code>file</code> in the file system.
105
* A new <code>FileDescriptor</code> object
106
* is created to represent this file connection.
108
* First, if there is a security manager,
109
* its <code>checkRead</code> method is called
110
* with the path represented by the <code>file</code>
111
* argument as its argument.
113
* If the named file does not exist, is a directory rather than a regular
114
* file, or for some other reason cannot be opened for reading then a
115
* <code>FileNotFoundException</code> is thrown.
117
* @param file the file to be opened for reading.
118
* @exception FileNotFoundException if the file does not exist,
119
* is a directory rather than a regular file,
120
* or for some other reason cannot be opened for
122
* @exception SecurityException if a security manager exists and its
123
* <code>checkRead</code> method denies read access to the file.
124
* @see java.io.File#getPath()
125
* @see java.lang.SecurityManager#checkRead(java.lang.String)
127
public FileInputStream(File file) throws FileNotFoundException {
128
String name = (file != null ? file.getPath() : null);
129
SecurityManager security = System.getSecurityManager();
130
if (security != null) {
131
security.checkRead(name);
134
throw new NullPointerException();
136
fd = new FileDescriptor();
137
fd.incrementAndGetUseCount();
142
* Creates a <code>FileInputStream</code> by using the file descriptor
143
* <code>fdObj</code>, which represents an existing connection to an
144
* actual file in the file system.
146
* If there is a security manager, its <code>checkRead</code> method is
147
* called with the file descriptor <code>fdObj</code> as its argument to
148
* see if it's ok to read the file descriptor. If read access is denied
149
* to the file descriptor a <code>SecurityException</code> is thrown.
151
* If <code>fdObj</code> is null then a <code>NullPointerException</code>
154
* This constructor does not throw an exception if <code>fdObj</code>
155
* is {@link java.io.FileDescriptor#valid() invalid}.
156
* However, if the methods are invoked on the resulting stream to attempt
157
* I/O on the stream, an <code>IOException</code> is thrown.
159
* @param fdObj the file descriptor to be opened for reading.
160
* @throws SecurityException if a security manager exists and its
161
* <code>checkRead</code> method denies read access to the
163
* @see SecurityManager#checkRead(java.io.FileDescriptor)
165
public FileInputStream(FileDescriptor fdObj) {
166
SecurityManager security = System.getSecurityManager();
168
throw new NullPointerException();
170
if (security != null) {
171
security.checkRead(fdObj);
176
* FileDescriptor is being shared by streams.
177
* Ensure that it's GC'ed only when all the streams/channels are done
180
fd.incrementAndGetUseCount();
184
* Opens the specified file for reading.
185
* @param name the name of the file
187
private void open(String name) throws FileNotFoundException
189
fd.openReadOnly(name);
193
* Reads a byte of data from this input stream. This method blocks
194
* if no input is yet available.
196
* @return the next byte of data, or <code>-1</code> if the end of the
198
* @exception IOException if an I/O error occurs.
200
public int read() throws IOException
206
* Reads a subarray as a sequence of bytes.
207
* @param b the data to be written
208
* @param off the start offset in the data
209
* @param len the number of bytes that are written
210
* @exception IOException If an I/O error has occurred.
212
private int readBytes(byte b[], int off, int len) throws IOException
214
return fd.readBytes(b, off, len);
218
* Reads up to <code>b.length</code> bytes of data from this input
219
* stream into an array of bytes. This method blocks until some input
222
* @param b the buffer into which the data is read.
223
* @return the total number of bytes read into the buffer, or
224
* <code>-1</code> if there is no more data because the end of
225
* the file has been reached.
226
* @exception IOException if an I/O error occurs.
228
public int read(byte b[]) throws IOException {
229
return readBytes(b, 0, b.length);
233
* Reads up to <code>len</code> bytes of data from this input stream
234
* into an array of bytes. If <code>len</code> is not zero, the method
235
* blocks until some input is available; otherwise, no
236
* bytes are read and <code>0</code> is returned.
238
* @param b the buffer into which the data is read.
239
* @param off the start offset in the destination array <code>b</code>
240
* @param len the maximum number of bytes read.
241
* @return the total number of bytes read into the buffer, or
242
* <code>-1</code> if there is no more data because the end of
243
* the file has been reached.
244
* @exception NullPointerException If <code>b</code> is <code>null</code>.
245
* @exception IndexOutOfBoundsException If <code>off</code> is negative,
246
* <code>len</code> is negative, or <code>len</code> is greater than
247
* <code>b.length - off</code>
248
* @exception IOException if an I/O error occurs.
250
public int read(byte b[], int off, int len) throws IOException {
251
return readBytes(b, off, len);
255
* Skips over and discards <code>n</code> bytes of data from the
258
* <p>The <code>skip</code> method may, for a variety of
259
* reasons, end up skipping over some smaller number of bytes,
260
* possibly <code>0</code>. If <code>n</code> is negative, an
261
* <code>IOException</code> is thrown, even though the <code>skip</code>
262
* method of the {@link InputStream} superclass does nothing in this case.
263
* The actual number of bytes skipped is returned.
265
* <p>This method may skip more bytes than are remaining in the backing
266
* file. This produces no exception and the number of bytes skipped
267
* may include some number of bytes that were beyond the EOF of the
268
* backing file. Attempting to read from the stream after skipping past
269
* the end will result in -1 indicating the end of the file.
271
* @param n the number of bytes to be skipped.
272
* @return the actual number of bytes skipped.
273
* @exception IOException if n is negative, if the stream does not
274
* support seek, or if an I/O error occurs.
276
public long skip(long n) throws IOException
282
* Returns an estimate of the number of remaining bytes that can be read (or
283
* skipped over) from this input stream without blocking by the next
284
* invocation of a method for this input stream. The next invocation might be
285
* the same thread or another thread. A single read or skip of this
286
* many bytes will not block, but may read or skip fewer bytes.
288
* <p> In some cases, a non-blocking read (or skip) may appear to be
289
* blocked when it is merely slow, for example when reading large
290
* files over slow networks.
292
* @return an estimate of the number of remaining bytes that can be read
293
* (or skipped over) from this input stream without blocking.
294
* @exception IOException if this file input stream has been closed by calling
295
* {@code close} or an I/O error occurs.
297
public int available() throws IOException
299
return fd.available();
303
* Closes this file input stream and releases any system resources
304
* associated with the stream.
306
* <p> If this stream has an associated channel then the channel is closed
309
* @exception IOException if an I/O error occurs.
314
public void close() throws IOException {
315
synchronized (closeLock) {
321
if (channel != null) {
323
* Decrement the FD use count associated with the channel
324
* The use count is incremented whenever a new channel
325
* is obtained from this stream.
327
fd.decrementAndGetUseCount();
332
* Decrement the FD use count associated with this stream
334
int useCount = fd.decrementAndGetUseCount();
337
* If FileDescriptor is still in use by another stream, the finalizer
340
if ((useCount <= 0) || !isRunningFinalize()) {
346
* Returns the <code>FileDescriptor</code>
347
* object that represents the connection to
348
* the actual file in the file system being
349
* used by this <code>FileInputStream</code>.
351
* @return the file descriptor object associated with this stream.
352
* @exception IOException if an I/O error occurs.
353
* @see java.io.FileDescriptor
355
public final FileDescriptor getFD() throws IOException {
356
if (fd != null) return fd;
357
throw new IOException();
361
* Returns the unique {@link java.nio.channels.FileChannel FileChannel}
362
* object associated with this file input stream.
364
* <p> The initial {@link java.nio.channels.FileChannel#position()
365
* </code>position<code>} of the returned channel will be equal to the
366
* number of bytes read from the file so far. Reading bytes from this
367
* stream will increment the channel's position. Changing the channel's
368
* position, either explicitly or by reading, will change this stream's
371
* @return the file channel associated with this file input stream
376
public FileChannel getChannel() {
377
synchronized (this) {
378
if (channel == null) {
379
channel = FileChannelImpl.open(fd, true, false, this);
382
* Increment fd's use count. Invoking the channel's close()
383
* method will result in decrementing the use count set for
386
fd.incrementAndGetUseCount();
392
private void close0() throws IOException
398
* Ensures that the <code>close</code> method of this file input stream is
399
* called when there are no more references to it.
401
* @exception IOException if an I/O error occurs.
402
* @see java.io.FileInputStream#close()
404
protected void finalize() throws IOException {
405
if ((fd != null) && (fd != FileDescriptor.in)) {
408
* Finalizer should not release the FileDescriptor if another
409
* stream is still using it. If the user directly invokes
410
* close() then the FileDescriptor is also released.
412
runningFinalize.set(Boolean.TRUE);
416
runningFinalize.set(Boolean.FALSE);