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