001/* FileInputStream.java -- An input stream that reads from disk files.
002   Copyright (C) 1998, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package java.io;
040
041import gnu.java.nio.FileChannelImpl;
042
043import java.nio.ByteBuffer;
044import java.nio.channels.FileChannel;
045
046/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
047 * "The Java Language Specification", ISBN 0-201-63451-1
048 * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
049 * Status:  Believed complete and correct.
050 */
051
052/**
053 * This class is a stream that reads its bytes from a file.
054 *
055 * @author Aaron M. Renn (arenn@urbanophile.com)
056 * @author Warren Levy (warrenl@cygnus.com)
057 */
058public class FileInputStream extends InputStream
059{
060  /**
061   * This is the native file handle for the file this stream is reading from
062   */
063  private FileDescriptor fd;
064
065  private FileChannelImpl ch;
066
067  /**
068   * This method initializes a <code>FileInputStream</code> to read from the
069   * specified named file.  A security check is first made to determine
070   * whether or not access to this file is allowed.  This is done by
071   * calling the <code>checkRead()</code> method of the
072   * <code>SecurityManager</code>
073   * (if one exists) with the name of this file.  An exception is thrown
074   * if reading is not allowed.  If the file does not exist, an exception
075   * is also thrown.
076   *
077   * @param name The name of the file this stream should read from
078   *
079   * @exception SecurityException If read access to the file is not allowed
080   * @exception FileNotFoundException If the file does not exist
081   * or if it is a directory
082   */
083  public FileInputStream(String name) throws FileNotFoundException
084  {
085    this(new File(name));
086  }
087
088  /**
089   * This method initializes a <code>FileInputStream</code> to read from the
090   * specified <code>File</code> object.  A security check is first
091   * made to determine
092   * whether or not access to this file is allowed.  This is done by
093   * calling the <code>checkRead()</code> method of the
094   * <code>SecurityManager</code>
095   * (if one exists) with the name of this file.  An exception is thrown
096   * if reading is not allowed.  If the file does not exist, an exception
097   * is also thrown.
098   *
099   * @param file The <code>File</code> object this stream should read from
100   *
101   * @exception SecurityException If read access to the file is not allowed
102   * @exception FileNotFoundException If the file does not exist
103   * or if it is a directory.
104   */
105  public FileInputStream(File file) throws FileNotFoundException
106  {
107    SecurityManager s = System.getSecurityManager();
108    if (s != null)
109      s.checkRead(file.getPath());
110
111    try
112      {
113        ch = FileChannelImpl.create(file, FileChannelImpl.READ);
114      }
115    catch (FileNotFoundException fnfe)
116      {
117        throw fnfe;
118      }
119    catch (IOException ioe)
120      {
121        FileNotFoundException fnfe = new FileNotFoundException(file.getPath());
122        fnfe.initCause(ioe);
123        throw fnfe;
124      }
125  }
126
127  /**
128   * This method initializes a <code>FileInputStream</code> to read from the
129   * specified <code>FileDescriptor</code> object.  A security
130   * check is first made to
131   * determine whether or not access to this file is allowed.  This is done by
132   * calling the <code>checkRead()</code> method of the
133   * <code>SecurityManager</code>
134   * (if one exists) with the specified <code>FileDescriptor</code>
135   * An exception is
136   * thrown if reading is not allowed.
137   *
138   * @param fdObj The <code>FileDescriptor</code> object this stream
139   * should read from
140   *
141   * @exception SecurityException If read access to the file is not allowed
142   */
143  public FileInputStream(FileDescriptor fdObj)
144  {
145    SecurityManager s = System.getSecurityManager();
146    if (s != null)
147      s.checkRead(fdObj);
148
149    fd = fdObj;
150    ch = (FileChannelImpl) fdObj.channel;
151  }
152
153  FileInputStream(FileChannelImpl ch)
154  {
155    this.ch = ch;
156  }
157
158  /**
159   * This method returns the number of bytes that can be read from this
160   * stream before a read can block.  A return of 0 indicates that blocking
161   * might (or might not) occur on the very next read attempt.
162   * <p>
163   * This method returns the number of unread bytes remaining in the file if
164   * the descriptor being read from is an actual file.  If this method is
165   * reading from a ''special'' file such a the standard input, this method
166   * will return the appropriate value for the stream being read.
167   * <p>
168   * Be aware that reads on plain files that do not reside locally might
169   * possibly block even if this method says they should not.  For example,
170   * a remote server might crash, preventing an NFS mounted file from being
171   * read.
172   *
173   * @return The number of bytes that can be read before blocking could occur
174   *
175   * @exception IOException If an error occurs
176   */
177  public int available() throws IOException
178  {
179    return ch.available();
180  }
181
182  /**
183   * This method closes the stream.  Any futher attempts to read from the
184   * stream will likely generate an IOException since the underlying file
185   * will be closed.
186   *
187   * @exception IOException If an error occurs.
188   */
189  public void close() throws IOException
190  {
191    ch.close();
192  }
193
194  protected void finalize() throws IOException
195  {
196    // We don't actually need this, but we include it because it is
197    // mentioned in the JCL.
198  }
199
200  /**
201   * This method returns a <code>FileDescriptor</code> object representing the
202   * underlying native file handle of the file this stream is reading
203   * from
204   *
205   * @return A <code>FileDescriptor</code> for this stream
206   *
207   * @exception IOException If an error occurs
208   */
209  public final FileDescriptor getFD() throws IOException
210  {
211    synchronized (this)
212      {
213        if (fd == null)
214          fd = new FileDescriptor (ch);
215        return fd;
216      }
217  }
218
219  /**
220   * This method reads an unsigned byte from the input stream and returns it
221   * as an int in the range of 0-255.  This method also will return -1 if
222   * the end of the stream has been reached.
223   * <p>
224   * This method will block until the byte can be read.
225   *
226   * @return The byte read or -1 if end of stream
227   *
228   * @exception IOException If an error occurs
229   */
230  public int read() throws IOException
231  {
232    return ch.read();
233  }
234
235  /**
236   * This method reads bytes from a stream and stores them into a caller
237   * supplied buffer.  This method attempts to completely fill the buffer,
238   * but can return before doing so.  The actual number of bytes read is
239   * returned as an int.  A -1 is returned to indicate the end of the stream.
240   * <p>
241   * This method will block until some data can be read.
242   * <p>
243   * This method operates by calling an overloaded read method like so:
244   * <code>read(buf, 0, buf.length)</code>
245   *
246   * @param buf The buffer into which the bytes read will be stored.
247   *
248   * @return The number of bytes read or -1 if end of stream.
249   *
250   * @exception IOException If an error occurs.
251   */
252  public int read(byte[] buf) throws IOException
253  {
254    return read(buf, 0, buf.length);
255  }
256
257  /**
258   * This method read bytes from a stream and stores them into a caller
259   * supplied buffer.  It starts storing the data at index
260   * <code>offset</code> into
261   * the buffer and attempts to read <code>len</code> bytes.  This method can
262   * return before reading the number of bytes requested.  The actual number
263   * of bytes read is returned as an int.  A -1 is returned to indicate the
264   * end of the stream.
265   * <p>
266   * This method will block until some data can be read.
267   *
268   * @param buf The array into which the bytes read should be stored
269   * @param offset The offset into the array to start storing bytes
270   * @param len The requested number of bytes to read
271   *
272   * @return The actual number of bytes read, or -1 if end of stream.
273   *
274   * @exception IOException If an error occurs.
275   */
276  public int read(byte[] buf, int offset, int len) throws IOException
277  {
278    if (offset < 0
279        || len < 0
280        || offset + len > buf.length)
281      throw new ArrayIndexOutOfBoundsException();
282
283    return ch.read(ByteBuffer.wrap(buf, offset, len));
284  }
285
286  /**
287   * This method skips the specified number of bytes in the stream.  It
288   * returns the actual number of bytes skipped, which may be less than the
289   * requested amount.
290   * <p>
291   * @param numBytes The requested number of bytes to skip
292   *
293   * @return The actual number of bytes skipped.
294   *
295   * @exception IOException If an error occurs
296   */
297  public synchronized long skip (long numBytes) throws IOException
298  {
299    if (numBytes < 0)
300      throw new IllegalArgumentException ("Can't skip negative bytes: " +
301                                          numBytes);
302
303    if (numBytes == 0)
304      return 0;
305
306    long oldPos = ch.position ();
307    ch.position(oldPos + numBytes);
308    return ch.position() - oldPos;
309  }
310
311  /**
312   * This method creates a java.nio.channels.FileChannel.
313   * Nio does not allow one to create a file channel directly.
314   * A file channel must be created by first creating an instance of
315   * Input/Output/RandomAccessFile and invoking the getChannel() method on it.
316   */
317  public synchronized FileChannel getChannel ()
318  {
319    return ch;
320  }
321
322} // class FileInputStream