1   /*
2    * @(#)FileInputStream.java 1.60 03/01/23
3    *
4    * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
5    * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6    */
7   
8   package java.io;
9   
10  import java.nio.channels.FileChannel;
11  import sun.nio.ch.FileChannelImpl;
12  
13  
14  /**
15   * A <code>FileInputStream</code> obtains input bytes
16   * from a file in a file system. What files
17   * are  available depends on the host environment.
18   *
19   * <p><code>FileInputStream</code> is meant for reading streams of raw bytes
20   * such as image data. For reading streams of characters, consider using
21   * <code>FileReader</code>.
22   *
23   * @author  Arthur van Hoff
24   * @version 1.60, 01/23/03
25   * @see     java.io.File
26   * @see     java.io.FileDescriptor
27   * @see     java.io.FileOutputStream
28   * @since   JDK1.0
29   */
30  public
31  class FileInputStream extends InputStream
32  {
33      /* File Descriptor - handle to the open file */
34      private FileDescriptor fd;
35  
36      private FileChannel channel = null;
37  
38      /**
39       * Creates a <code>FileInputStream</code> by
40       * opening a connection to an actual file,
41       * the file named by the path name <code>name</code>
42       * in the file system.  A new <code>FileDescriptor</code>
43       * object is created to represent this file
44       * connection.
45       * <p>
46       * First, if there is a security
47       * manager, its <code>checkRead</code> method
48       * is called with the <code>name</code> argument
49       * as its argument.
50       * <p>
51       * If the named file does not exist, is a directory rather than a regular
52       * file, or for some other reason cannot be opened for reading then a
53       * <code>FileNotFoundException</code> is thrown.
54       *
55       * @param      name   the system-dependent file name.
56       * @exception  FileNotFoundException  if the file does not exist,
57       *                   is a directory rather than a regular file,
58       *                   or for some other reason cannot be opened for
59       *                   reading.
60       * @exception  SecurityException      if a security manager exists and its
61       *               <code>checkRead</code> method denies read access
62       *               to the file.
63       * @see        java.lang.SecurityManager#checkRead(java.lang.String)
64       */
65      public FileInputStream(String name) throws FileNotFoundException {
66          this(name != null ? new File(name) : null);
67      }
68  
69      /**
70       * Creates a <code>FileInputStream</code> by
71       * opening a connection to an actual file,
72       * the file named by the <code>File</code>
73       * object <code>file</code> in the file system.
74       * A new <code>FileDescriptor</code> object
75       * is created to represent this file connection.
76       * <p>
77       * First, if there is a security manager,
78       * its <code>checkRead</code> method  is called
79       * with the path represented by the <code>file</code>
80       * argument as its argument.
81       * <p>
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.
85       *
86       * @param      file   the file to be opened for reading.
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
90       *                   reading.
91       * @exception  SecurityException      if a security manager exists and its
92       *               <code>checkRead</code> method denies read access to the file.
93       * @see        java.io.File#getPath()
94       * @see        java.lang.SecurityManager#checkRead(java.lang.String)
95       */
96      public FileInputStream(File file) throws FileNotFoundException {
97      String name = (file != null ? file.getPath() : null);
98      SecurityManager security = System.getSecurityManager();
99      if (security != null) {
100         security.checkRead(name);
101     }
102         if (name == null) {
103             throw new NullPointerException();
104         }
105     fd = new FileDescriptor();
106     open(name);
107     }
108 
109     /**
110      * Creates a <code>FileInputStream</code> by using the file descriptor
111      * <code>fdObj</code>, which represents an existing connection to an
112      * actual file in the file system.
113      * <p>
114      * If there is a security manager, its <code>checkRead</code> method is
115      * called with the file descriptor <code>fdObj</code> as its argument to
116      * see if it's ok to read the file descriptor. If read access is denied
117      * to the file descriptor a <code>SecurityException</code> is thrown.
118      * <p>
119      * If <code>fdObj</code> is null then a <code>NullPointerException</code>
120      * is thrown.
121      *
122      * @param      fdObj   the file descriptor to be opened for reading.
123      * @throws     SecurityException      if a security manager exists and its
124      *                 <code>checkRead</code> method denies read access to the
125      *                 file descriptor.
126      * @see        SecurityManager#checkRead(java.io.FileDescriptor)
127      */
128     public FileInputStream(FileDescriptor fdObj) {
129     SecurityManager security = System.getSecurityManager();
130     if (fdObj == null) {
131         throw new NullPointerException();
132     }
133     if (security != null) {
134         security.checkRead(fdObj);
135     }
136     fd = fdObj;
137     }
138 
139     /**
140      * Opens the specified file for reading.
141      * @param name the name of the file
142      */
143     private native void open(String name) throws FileNotFoundException;
144 
145     /**
146      * Reads a byte of data from this input stream. This method blocks
147      * if no input is yet available.
148      *
149      * @return     the next byte of data, or <code>-1</code> if the end of the
150      *             file is reached.
151      * @exception  IOException  if an I/O error occurs.
152      */
153     public native int read() throws IOException;
154 
155 
156     /**
157      * Reads a subarray as a sequence of bytes.
158      * @param b the data to be written
159      * @param off the start offset in the data
160      * @param len the number of bytes that are written
161      * @exception IOException If an I/O error has occurred.
162      */
163     private native int readBytes(byte b[], int off, int len) throws IOException;
164 
165     /**
166      * Reads up to <code>b.length</code> bytes of data from this input
167      * stream into an array of bytes. This method blocks until some input
168      * is available.
169      *
170      * @param      b   the buffer into which the data is read.
171      * @return     the total number of bytes read into the buffer, or
172      *             <code>-1</code> if there is no more data because the end of
173      *             the file has been reached.
174      * @exception  IOException  if an I/O error occurs.
175      */
176     public int read(byte b[]) throws IOException {
177     return readBytes(b, 0, b.length);
178     }
179 
180     /**
181      * Reads up to <code>len</code> bytes of data from this input stream
182      * into an array of bytes. This method blocks until some input is
183      * available.
184      *
185      * @param      b     the buffer into which the data is read.
186      * @param      off   the start offset of the data.
187      * @param      len   the maximum number of bytes read.
188      * @return     the total number of bytes read into the buffer, or
189      *             <code>-1</code> if there is no more data because the end of
190      *             the file has been reached.
191      * @exception  IOException  if an I/O error occurs.
192      */
193     public int read(byte b[], int off, int len) throws IOException {
194     return readBytes(b, off, len);
195     }
196 
197     /**
198      * Skips over and discards <code>n</code> bytes of data from the
199      * input stream. The <code>skip</code> method may, for a variety of
200      * reasons, end up skipping over some smaller number of bytes,
201      * possibly <code>0</code>. The actual number of bytes skipped is returned.
202      *
203      * @param      n   the number of bytes to be skipped.
204      * @return     the actual number of bytes skipped.
205      * @exception  IOException  if an I/O error occurs.
206      */
207     public native long skip(long n) throws IOException;
208 
209     /**
210      * Returns the number of bytes that can be read from this file input
211      * stream without blocking.
212      *
213      * @return     the number of bytes that can be read from this file input
214      *             stream without blocking.
215      * @exception  IOException  if an I/O error occurs.
216      */
217     public native int available() throws IOException;
218 
219     /**
220      * Closes this file input stream and releases any system resources
221      * associated with the stream.
222      *
223      * <p> If this stream has an associated channel then the channel is closed
224      * as well.
225      *
226      * @exception  IOException  if an I/O error occurs.
227      *
228      * @revised 1.4
229      * @spec JSR-51
230      */
231     public void close() throws IOException {
232         if (channel != null)
233             channel.close();
234         close0();
235     }
236 
237     /**
238      * Returns the <code>FileDescriptor</code>
239      * object  that represents the connection to
240      * the actual file in the file system being
241      * used by this <code>FileInputStream</code>.
242      *
243      * @return     the file descriptor object associated with this stream.
244      * @exception  IOException  if an I/O error occurs.
245      * @see        java.io.FileDescriptor
246      */
247     public final FileDescriptor getFD() throws IOException {
248     if (fd != null) return fd;
249     throw new IOException();
250     }
251 
252     /**
253      * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
254      * object associated with this file input stream.
255      *
256      * <p> The initial {@link java.nio.channels.FileChannel#position()
257      * </code>position<code>} of the returned channel will be equal to the
258      * number of bytes read from the file so far.  Reading bytes from this
259      * stream will increment the channel's position.  Changing the channel's
260      * position, either explicitly or by reading, will change this stream's
261      * file position.
262      *
263      * @return  the file channel associated with this file input stream
264      *
265      * @since 1.4
266      * @spec JSR-51
267      */
268     public FileChannel getChannel() {
269     synchronized (this) {
270         if (channel == null)
271         channel = FileChannelImpl.open(fd, true, false, this);
272         return channel;
273     }
274     }
275 
276     private static native void initIDs();
277 
278     private native void close0() throws IOException;
279 
280     static {
281     initIDs();
282     }
283 
284     /**
285      * Ensures that the <code>close</code> method of this file input stream is
286      * called when there are no more references to it.
287      *
288      * @exception  IOException  if an I/O error occurs.
289      * @see        java.io.FileInputStream#close()
290      */
291     protected void finalize() throws IOException {
292     if (fd != null) {
293         if (fd != fd.in) {
294         close();
295         }
296     }
297     }
298 }
299