1. /*
  2. * @(#)FileOutputStream.java 1.56 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. package java.io;
  8. import java.nio.channels.FileChannel;
  9. import sun.nio.ch.FileChannelImpl;
  10. /**
  11. * A file output stream is an output stream for writing data to a
  12. * <code>File</code> or to a <code>FileDescriptor</code>. Whether or not
  13. * a file is available or may be created depends upon the underlying
  14. * platform. Some platforms, in particular, allow a file to be opened
  15. * for writing by only one <tt>FileOutputStream</tt> (or other
  16. * file-writing object) at a time. In such situations the constructors in
  17. * this class will fail if the file involved is already open.
  18. *
  19. * <p><code>FileOutputStream</code> is meant for writing streams of raw bytes
  20. * such as image data. For writing streams of characters, consider using
  21. * <code>FileWriter</code>.
  22. *
  23. * @author Arthur van Hoff
  24. * @version 1.56, 01/23/03
  25. * @see java.io.File
  26. * @see java.io.FileDescriptor
  27. * @see java.io.FileInputStream
  28. * @since JDK1.0
  29. */
  30. public
  31. class FileOutputStream extends OutputStream
  32. {
  33. /**
  34. * The system dependent file descriptor. The value is
  35. * 1 more than actual file descriptor. This means that
  36. * the default value 0 indicates that the file is not open.
  37. */
  38. private FileDescriptor fd;
  39. private FileChannel channel= null;
  40. private boolean append = false;
  41. /**
  42. * Creates an output file stream to write to the file with the
  43. * specified name. A new <code>FileDescriptor</code> object is
  44. * created to represent this file connection.
  45. * <p>
  46. * First, if there is a security manager, its <code>checkWrite</code>
  47. * method is called with <code>name</code> as its argument.
  48. * <p>
  49. * If the file exists but is a directory rather than a regular file, does
  50. * not exist but cannot be created, or cannot be opened for any other
  51. * reason then a <code>FileNotFoundException</code> is thrown.
  52. *
  53. * @param name the system-dependent filename
  54. * @exception FileNotFoundException if the file exists but is a directory
  55. * rather than a regular file, does not exist but cannot
  56. * be created, or cannot be opened for any other reason
  57. * @exception SecurityException if a security manager exists and its
  58. * <code>checkWrite</code> method denies write access
  59. * to the file.
  60. * @see java.lang.SecurityManager#checkWrite(java.lang.String)
  61. */
  62. public FileOutputStream(String name) throws FileNotFoundException {
  63. this(name != null ? new File(name) : null, false);
  64. }
  65. /**
  66. * Creates an output file stream to write to the file with the specified
  67. * <code>name</code>. If the second argument is <code>true</code>, then
  68. * bytes will be written to the end of the file rather than the beginning.
  69. * A new <code>FileDescriptor</code> object is created to represent this
  70. * file connection.
  71. * <p>
  72. * First, if there is a security manager, its <code>checkWrite</code>
  73. * method is called with <code>name</code> as its argument.
  74. * <p>
  75. * If the file exists but is a directory rather than a regular file, does
  76. * not exist but cannot be created, or cannot be opened for any other
  77. * reason then a <code>FileNotFoundException</code> is thrown.
  78. *
  79. * @param name the system-dependent file name
  80. * @param append if <code>true</code>, then bytes will be written
  81. * to the end of the file rather than the beginning
  82. * @exception FileNotFoundException if the file exists but is a directory
  83. * rather than a regular file, does not exist but cannot
  84. * be created, or cannot be opened for any other reason.
  85. * @exception SecurityException if a security manager exists and its
  86. * <code>checkWrite</code> method denies write access
  87. * to the file.
  88. * @see java.lang.SecurityManager#checkWrite(java.lang.String)
  89. * @since JDK1.1
  90. */
  91. public FileOutputStream(String name, boolean append)
  92. throws FileNotFoundException
  93. {
  94. this(name != null ? new File(name) : null, append);
  95. }
  96. /**
  97. * Creates a file output stream to write to the file represented by
  98. * the specified <code>File</code> object. A new
  99. * <code>FileDescriptor</code> object is created to represent this
  100. * file connection.
  101. * <p>
  102. * First, if there is a security manager, its <code>checkWrite</code>
  103. * method is called with the path represented by the <code>file</code>
  104. * argument as its argument.
  105. * <p>
  106. * If the file exists but is a directory rather than a regular file, does
  107. * not exist but cannot be created, or cannot be opened for any other
  108. * reason then a <code>FileNotFoundException</code> is thrown.
  109. *
  110. * @param file the file to be opened for writing.
  111. * @exception FileNotFoundException if the file exists but is a directory
  112. * rather than a regular file, does not exist but cannot
  113. * be created, or cannot be opened for any other reason
  114. * @exception SecurityException if a security manager exists and its
  115. * <code>checkWrite</code> method denies write access
  116. * to the file.
  117. * @see java.io.File#getPath()
  118. * @see java.lang.SecurityException
  119. * @see java.lang.SecurityManager#checkWrite(java.lang.String)
  120. */
  121. public FileOutputStream(File file) throws FileNotFoundException {
  122. this(file, false);
  123. }
  124. /**
  125. * Creates a file output stream to write to the file represented by
  126. * the specified <code>File</code> object. If the second argument is
  127. * <code>true</code>, then bytes will be written to the end of the file
  128. * rather than the beginning. A new <code>FileDescriptor</code> object is
  129. * created to represent this file connection.
  130. * <p>
  131. * First, if there is a security manager, its <code>checkWrite</code>
  132. * method is called with the path represented by the <code>file</code>
  133. * argument as its argument.
  134. * <p>
  135. * If the file exists but is a directory rather than a regular file, does
  136. * not exist but cannot be created, or cannot be opened for any other
  137. * reason then a <code>FileNotFoundException</code> is thrown.
  138. *
  139. * @param file the file to be opened for writing.
  140. * @param append if <code>true</code>, then bytes will be written
  141. * to the end of the file rather than the beginning
  142. * @exception FileNotFoundException if the file exists but is a directory
  143. * rather than a regular file, does not exist but cannot
  144. * be created, or cannot be opened for any other reason
  145. * @exception SecurityException if a security manager exists and its
  146. * <code>checkWrite</code> method denies write access
  147. * to the file.
  148. * @see java.io.File#getPath()
  149. * @see java.lang.SecurityException
  150. * @see java.lang.SecurityManager#checkWrite(java.lang.String)
  151. * @since 1.4
  152. */
  153. public FileOutputStream(File file, boolean append)
  154. throws FileNotFoundException
  155. {
  156. String name = (file != null ? file.getPath() : null);
  157. SecurityManager security = System.getSecurityManager();
  158. if (security != null) {
  159. security.checkWrite(name);
  160. }
  161. if (name == null) {
  162. throw new NullPointerException();
  163. }
  164. fd = new FileDescriptor();
  165. this.append = append;
  166. if (append) {
  167. openAppend(name);
  168. } else {
  169. open(name);
  170. }
  171. }
  172. /**
  173. * Creates an output file stream to write to the specified file
  174. * descriptor, which represents an existing connection to an actual
  175. * file in the file system.
  176. * <p>
  177. * First, if there is a security manager, its <code>checkWrite</code>
  178. * method is called with the file descriptor <code>fdObj</code>
  179. * argument as its argument.
  180. *
  181. * @param fdObj the file descriptor to be opened for writing
  182. * @exception SecurityException if a security manager exists and its
  183. * <code>checkWrite</code> method denies
  184. * write access to the file descriptor
  185. * @see java.lang.SecurityManager#checkWrite(java.io.FileDescriptor)
  186. */
  187. public FileOutputStream(FileDescriptor fdObj) {
  188. SecurityManager security = System.getSecurityManager();
  189. if (fdObj == null) {
  190. throw new NullPointerException();
  191. }
  192. if (security != null) {
  193. security.checkWrite(fdObj);
  194. }
  195. fd = fdObj;
  196. }
  197. /**
  198. * Opens a file, with the specified name, for writing.
  199. * @param name name of file to be opened
  200. */
  201. private native void open(String name) throws FileNotFoundException;
  202. /**
  203. * Opens a file, with the specified name, for appending.
  204. * @param name name of file to be opened
  205. */
  206. private native void openAppend(String name) throws FileNotFoundException;
  207. /**
  208. * Writes the specified byte to this file output stream. Implements
  209. * the <code>write</code> method of <code>OutputStream</code>.
  210. *
  211. * @param b the byte to be written.
  212. * @exception IOException if an I/O error occurs.
  213. */
  214. public native void write(int b) throws IOException;
  215. /**
  216. * Writes a sub array as a sequence of bytes.
  217. * @param b the data to be written
  218. * @param off the start offset in the data
  219. * @param len the number of bytes that are written
  220. * @exception IOException If an I/O error has occurred.
  221. */
  222. private native void writeBytes(byte b[], int off, int len) throws IOException;
  223. /**
  224. * Writes <code>b.length</code> bytes from the specified byte array
  225. * to this file output stream.
  226. *
  227. * @param b the data.
  228. * @exception IOException if an I/O error occurs.
  229. */
  230. public void write(byte b[]) throws IOException {
  231. writeBytes(b, 0, b.length);
  232. }
  233. /**
  234. * Writes <code>len</code> bytes from the specified byte array
  235. * starting at offset <code>off</code> to this file output stream.
  236. *
  237. * @param b the data.
  238. * @param off the start offset in the data.
  239. * @param len the number of bytes to write.
  240. * @exception IOException if an I/O error occurs.
  241. */
  242. public void write(byte b[], int off, int len) throws IOException {
  243. writeBytes(b, off, len);
  244. }
  245. /**
  246. * Closes this file output stream and releases any system resources
  247. * associated with this stream. This file output stream may no longer
  248. * be used for writing bytes.
  249. *
  250. * <p> If this stream has an associated channel then the channel is closed
  251. * as well.
  252. *
  253. * @exception IOException if an I/O error occurs.
  254. *
  255. * @revised 1.4
  256. * @spec JSR-51
  257. */
  258. public void close() throws IOException {
  259. if (channel != null)
  260. channel.close();
  261. close0();
  262. }
  263. /**
  264. * Returns the file descriptor associated with this stream.
  265. *
  266. * @return the <code>FileDescriptor</code> object that represents
  267. * the connection to the file in the file system being used
  268. * by this <code>FileOutputStream</code> object.
  269. *
  270. * @exception IOException if an I/O error occurs.
  271. * @see java.io.FileDescriptor
  272. */
  273. public final FileDescriptor getFD() throws IOException {
  274. if (fd != null) return fd;
  275. throw new IOException();
  276. }
  277. /**
  278. * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
  279. * object associated with this file output stream. </p>
  280. *
  281. * <p> The initial {@link java.nio.channels.FileChannel#position()
  282. * </code>position<code>} of the returned channel will be equal to the
  283. * number of bytes written to the file so far unless this stream is in
  284. * append mode, in which case it will be equal to the size of the file.
  285. * Writing bytes to this stream will increment the channel's position
  286. * accordingly. Changing the channel's position, either explicitly or by
  287. * writing, will change this stream's file position.
  288. *
  289. * @return the file channel associated with this file output stream
  290. *
  291. * @since 1.4
  292. * @spec JSR-51
  293. */
  294. public FileChannel getChannel() {
  295. synchronized (this) {
  296. if (channel == null)
  297. channel = FileChannelImpl.open(fd, false, true, this, append);
  298. return channel;
  299. }
  300. }
  301. /**
  302. * Cleans up the connection to the file, and ensures that the
  303. * <code>close</code> method of this file output stream is
  304. * called when there are no more references to this stream.
  305. *
  306. * @exception IOException if an I/O error occurs.
  307. * @see java.io.FileInputStream#close()
  308. */
  309. protected void finalize() throws IOException {
  310. if (fd != null) {
  311. if (fd == fd.out || fd == fd.err) {
  312. flush();
  313. } else {
  314. close();
  315. }
  316. }
  317. }
  318. private native void close0() throws IOException;
  319. private static native void initIDs();
  320. static {
  321. initIDs();
  322. }
  323. }