2 * Copyright (c) 1994, 2011, 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
31 * A file output stream is an output stream for writing data to a
32 * <code>File</code> or to a <code>FileDescriptor</code>. Whether or not
33 * a file is available or may be created depends upon the underlying
34 * platform. Some platforms, in particular, allow a file to be opened
35 * for writing by only one <tt>FileOutputStream</tt> (or other
36 * file-writing object) at a time. In such situations the constructors in
37 * this class will fail if the file involved is already open.
39 * <p><code>FileOutputStream</code> is meant for writing streams of raw bytes
40 * such as image data. For writing streams of characters, consider using
41 * <code>FileWriter</code>.
43 * @author Arthur van Hoff
45 * @see java.io.FileDescriptor
46 * @see java.io.FileInputStream
47 * @see java.nio.file.Files#newOutputStream
51 class FileOutputStream extends OutputStream
54 * The system dependent file descriptor.
56 private final FileDescriptor fd;
59 * True if the file is opened for append.
61 private final boolean append;
64 * The associated channel, initalized lazily.
66 // private FileChannel channel;
68 private final Object closeLock = new Object();
69 private volatile boolean closed = false;
70 private static final ThreadLocal<Boolean> runningFinalize =
73 private static boolean isRunningFinalize() {
75 if ((val = runningFinalize.get()) != null)
76 return val.booleanValue();
81 * Creates a file output stream to write to the file with the
82 * specified name. A new <code>FileDescriptor</code> object is
83 * created to represent this file connection.
85 * First, if there is a security manager, its <code>checkWrite</code>
86 * method is called with <code>name</code> as its argument.
88 * If the file exists but is a directory rather than a regular file, does
89 * not exist but cannot be created, or cannot be opened for any other
90 * reason then a <code>FileNotFoundException</code> is thrown.
92 * @param name the system-dependent filename
93 * @exception FileNotFoundException if the file exists but is a directory
94 * rather than a regular file, does not exist but cannot
95 * be created, or cannot be opened for any other reason
96 * @exception SecurityException if a security manager exists and its
97 * <code>checkWrite</code> method denies write access
99 * @see java.lang.SecurityManager#checkWrite(java.lang.String)
101 public FileOutputStream(String name) throws FileNotFoundException {
102 this(name != null ? new File(name) : null, false);
106 * Creates a file output stream to write to the file with the specified
107 * name. If the second argument is <code>true</code>, then
108 * bytes will be written to the end of the file rather than the beginning.
109 * A new <code>FileDescriptor</code> object is created to represent this
112 * First, if there is a security manager, its <code>checkWrite</code>
113 * method is called with <code>name</code> as its argument.
115 * If the file exists but is a directory rather than a regular file, does
116 * not exist but cannot be created, or cannot be opened for any other
117 * reason then a <code>FileNotFoundException</code> is thrown.
119 * @param name the system-dependent file name
120 * @param append if <code>true</code>, then bytes will be written
121 * to the end of the file rather than the beginning
122 * @exception FileNotFoundException if the file exists but is a directory
123 * rather than a regular file, does not exist but cannot
124 * be created, or cannot be opened for any other reason.
125 * @exception SecurityException if a security manager exists and its
126 * <code>checkWrite</code> method denies write access
128 * @see java.lang.SecurityManager#checkWrite(java.lang.String)
131 public FileOutputStream(String name, boolean append)
132 throws FileNotFoundException
134 this(name != null ? new File(name) : null, append);
138 * Creates a file output stream to write to the file represented by
139 * the specified <code>File</code> object. A new
140 * <code>FileDescriptor</code> object is created to represent this
143 * First, if there is a security manager, its <code>checkWrite</code>
144 * method is called with the path represented by the <code>file</code>
145 * argument as its argument.
147 * If the file exists but is a directory rather than a regular file, does
148 * not exist but cannot be created, or cannot be opened for any other
149 * reason then a <code>FileNotFoundException</code> is thrown.
151 * @param file the file to be opened for writing.
152 * @exception FileNotFoundException if the file exists but is a directory
153 * rather than a regular file, does not exist but cannot
154 * be created, or cannot be opened for any other reason
155 * @exception SecurityException if a security manager exists and its
156 * <code>checkWrite</code> method denies write access
158 * @see java.io.File#getPath()
159 * @see java.lang.SecurityException
160 * @see java.lang.SecurityManager#checkWrite(java.lang.String)
162 public FileOutputStream(File file) throws FileNotFoundException {
167 * Creates a file output stream to write to the file represented by
168 * the specified <code>File</code> object. If the second argument is
169 * <code>true</code>, then bytes will be written to the end of the file
170 * rather than the beginning. A new <code>FileDescriptor</code> object is
171 * created to represent this file connection.
173 * First, if there is a security manager, its <code>checkWrite</code>
174 * method is called with the path represented by the <code>file</code>
175 * argument as its argument.
177 * If the file exists but is a directory rather than a regular file, does
178 * not exist but cannot be created, or cannot be opened for any other
179 * reason then a <code>FileNotFoundException</code> is thrown.
181 * @param file the file to be opened for writing.
182 * @param append if <code>true</code>, then bytes will be written
183 * to the end of the file rather than the beginning
184 * @exception FileNotFoundException if the file exists but is a directory
185 * rather than a regular file, does not exist but cannot
186 * be created, or cannot be opened for any other reason
187 * @exception SecurityException if a security manager exists and its
188 * <code>checkWrite</code> method denies write access
190 * @see java.io.File#getPath()
191 * @see java.lang.SecurityException
192 * @see java.lang.SecurityManager#checkWrite(java.lang.String)
195 public FileOutputStream(File file, boolean append)
196 throws FileNotFoundException
198 throw new SecurityException();
202 * Creates a file output stream to write to the specified file
203 * descriptor, which represents an existing connection to an actual
204 * file in the file system.
206 * First, if there is a security manager, its <code>checkWrite</code>
207 * method is called with the file descriptor <code>fdObj</code>
208 * argument as its argument.
210 * If <code>fdObj</code> is null then a <code>NullPointerException</code>
213 * This constructor does not throw an exception if <code>fdObj</code>
214 * is {@link java.io.FileDescriptor#valid() invalid}.
215 * However, if the methods are invoked on the resulting stream to attempt
216 * I/O on the stream, an <code>IOException</code> is thrown.
218 * @param fdObj the file descriptor to be opened for writing
219 * @exception SecurityException if a security manager exists and its
220 * <code>checkWrite</code> method denies
221 * write access to the file descriptor
222 * @see java.lang.SecurityManager#checkWrite(java.io.FileDescriptor)
224 public FileOutputStream(FileDescriptor fdObj) {
225 throw new SecurityException();
229 * Opens a file, with the specified name, for overwriting or appending.
230 * @param name name of file to be opened
231 * @param append whether the file is to be opened in append mode
233 private native void open(String name, boolean append)
234 throws FileNotFoundException;
237 * Writes the specified byte to this file output stream.
239 * @param b the byte to be written.
240 * @param append {@code true} if the write operation first
241 * advances the position to the end of file
243 private native void write(int b, boolean append) throws IOException;
246 * Writes the specified byte to this file output stream. Implements
247 * the <code>write</code> method of <code>OutputStream</code>.
249 * @param b the byte to be written.
250 * @exception IOException if an I/O error occurs.
252 public void write(int b) throws IOException {
257 * Writes a sub array as a sequence of bytes.
258 * @param b the data to be written
259 * @param off the start offset in the data
260 * @param len the number of bytes that are written
261 * @param append {@code true} to first advance the position to the
263 * @exception IOException If an I/O error has occurred.
265 private native void writeBytes(byte b[], int off, int len, boolean append)
269 * Writes <code>b.length</code> bytes from the specified byte array
270 * to this file output stream.
273 * @exception IOException if an I/O error occurs.
275 public void write(byte b[]) throws IOException {
276 writeBytes(b, 0, b.length, append);
280 * Writes <code>len</code> bytes from the specified byte array
281 * starting at offset <code>off</code> to this file output stream.
284 * @param off the start offset in the data.
285 * @param len the number of bytes to write.
286 * @exception IOException if an I/O error occurs.
288 public void write(byte b[], int off, int len) throws IOException {
289 writeBytes(b, off, len, append);
293 * Closes this file output stream and releases any system resources
294 * associated with this stream. This file output stream may no longer
295 * be used for writing bytes.
297 * <p> If this stream has an associated channel then the channel is closed
300 * @exception IOException if an I/O error occurs.
305 public void close() throws IOException {
306 synchronized (closeLock) {
313 // if (channel != null) {
315 // * Decrement FD use count associated with the channel
316 // * The use count is incremented whenever a new channel
317 // * is obtained from this stream.
319 // fd.decrementAndGetUseCount();
324 * Decrement FD use count associated with this stream
326 int useCount = fd.decrementAndGetUseCount();
329 * If FileDescriptor is still in use by another stream, the finalizer
332 if ((useCount <= 0) || !isRunningFinalize()) {
338 * Returns the file descriptor associated with this stream.
340 * @return the <code>FileDescriptor</code> object that represents
341 * the connection to the file in the file system being used
342 * by this <code>FileOutputStream</code> object.
344 * @exception IOException if an I/O error occurs.
345 * @see java.io.FileDescriptor
347 public final FileDescriptor getFD() throws IOException {
348 if (fd != null) return fd;
349 throw new IOException();
353 * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
354 * object associated with this file output stream. </p>
356 * <p> The initial {@link java.nio.channels.FileChannel#position()
357 * </code>position<code>} of the returned channel will be equal to the
358 * number of bytes written to the file so far unless this stream is in
359 * append mode, in which case it will be equal to the size of the file.
360 * Writing bytes to this stream will increment the channel's position
361 * accordingly. Changing the channel's position, either explicitly or by
362 * writing, will change this stream's file position.
364 * @return the file channel associated with this file output stream
369 // public FileChannel getChannel() {
370 // synchronized (this) {
371 // if (channel == null) {
372 // channel = FileChannelImpl.open(fd, false, true, append, this);
375 // * Increment fd's use count. Invoking the channel's close()
376 // * method will result in decrementing the use count set for
379 // fd.incrementAndGetUseCount();
386 * Cleans up the connection to the file, and ensures that the
387 * <code>close</code> method of this file output stream is
388 * called when there are no more references to this stream.
390 * @exception IOException if an I/O error occurs.
391 * @see java.io.FileInputStream#close()
393 protected void finalize() throws IOException {
395 if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
400 * Finalizer should not release the FileDescriptor if another
401 * stream is still using it. If the user directly invokes
402 * close() then the FileDescriptor is also released.
404 runningFinalize.set(Boolean.TRUE);
408 runningFinalize.set(Boolean.FALSE);
414 private native void close0() throws IOException;
416 private static native void initIDs();