9 * by Oracle in the LICENSE file that accompanied this code.
10 *
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).
16 *
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.
20 *
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
23 * questions.
24 */
25
26 package java.io;
27
28 import java.nio.channels.FileChannel;
29 import sun.misc.SharedSecrets;
30 import sun.misc.JavaIOFileDescriptorAccess;
31 import sun.nio.ch.FileChannelImpl;
32
33
34 /**
35 * A file output stream is an output stream for writing data to a
36 * <code>File</code> or to a <code>FileDescriptor</code>. Whether or not
37 * a file is available or may be created depends upon the underlying
38 * platform. Some platforms, in particular, allow a file to be opened
39 * for writing by only one <tt>FileOutputStream</tt> (or other
40 * file-writing object) at a time. In such situations the constructors in
41 * this class will fail if the file involved is already open.
42 *
43 * <p><code>FileOutputStream</code> is meant for writing streams of raw bytes
44 * such as image data. For writing streams of characters, consider using
45 * <code>FileWriter</code>.
46 *
47 * @author Arthur van Hoff
48 * @see java.io.File
59 */
60 private static final JavaIOFileDescriptorAccess fdAccess =
61 SharedSecrets.getJavaIOFileDescriptorAccess();
62
63 /**
64 * The system dependent file descriptor.
65 */
66 private final FileDescriptor fd;
67
68 /**
69 * The associated channel, initialized lazily.
70 */
71 private FileChannel channel;
72
73 /**
74 * The path of the referenced file
75 * (null if the stream is created with a file descriptor)
76 */
77 private final String path;
78
79 private final Object closeLock = new Object();
80 private volatile boolean closed = false;
81
82 /**
83 * Creates a file output stream to write to the file with the
84 * specified name. A new <code>FileDescriptor</code> object is
85 * created to represent this file connection.
86 * <p>
87 * First, if there is a security manager, its <code>checkWrite</code>
88 * method is called with <code>name</code> as its argument.
89 * <p>
90 * If the file exists but is a directory rather than a regular file, does
91 * not exist but cannot be created, or cannot be opened for any other
92 * reason then a <code>FileNotFoundException</code> is thrown.
93 *
94 * @param name the system-dependent filename
95 * @exception FileNotFoundException if the file exists but is a directory
96 * rather than a regular file, does not exist but cannot
97 * be created, or cannot be opened for any other reason
98 * @exception SecurityException if a security manager exists and its
99 * <code>checkWrite</code> method denies write access
100 * to the file.
324 * @exception IOException if an I/O error occurs.
325 */
326 public void write(byte b[], int off, int len) throws IOException {
327 writeBytes(b, off, len, fdAccess.getAppend(fd));
328 }
329
330 /**
331 * Closes this file output stream and releases any system resources
332 * associated with this stream. This file output stream may no longer
333 * be used for writing bytes.
334 *
335 * <p> If this stream has an associated channel then the channel is closed
336 * as well.
337 *
338 * @exception IOException if an I/O error occurs.
339 *
340 * @revised 1.4
341 * @spec JSR-51
342 */
343 public void close() throws IOException {
344 synchronized (closeLock) {
345 if (closed) {
346 return;
347 }
348 closed = true;
349 }
350
351 if (channel != null) {
352 channel.close();
353 }
354
355 fd.closeAll(new Closeable() {
356 public void close() throws IOException {
357 close0();
358 }
359 });
360 }
361
362 /**
363 * Returns the file descriptor associated with this stream.
364 *
365 * @return the <code>FileDescriptor</code> object that represents
366 * the connection to the file in the file system being used
367 * by this <code>FileOutputStream</code> object.
368 *
369 * @exception IOException if an I/O error occurs.
380 * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
381 * object associated with this file output stream.
382 *
383 * <p> The initial {@link java.nio.channels.FileChannel#position()
384 * position} of the returned channel will be equal to the
385 * number of bytes written to the file so far unless this stream is in
386 * append mode, in which case it will be equal to the size of the file.
387 * Writing bytes to this stream will increment the channel's position
388 * accordingly. Changing the channel's position, either explicitly or by
389 * writing, will change this stream's file position.
390 *
391 * @return the file channel associated with this file output stream
392 *
393 * @since 1.4
394 * @spec JSR-51
395 */
396 public FileChannel getChannel() {
397 synchronized (this) {
398 if (channel == null) {
399 channel = FileChannelImpl.open(fd, path, false, true, this);
400 }
401 return channel;
402 }
403 }
404
405 /**
406 * Cleans up the connection to the file, and ensures that the
407 * <code>close</code> method of this file output stream is
408 * called when there are no more references to this stream.
409 *
410 * @exception IOException if an I/O error occurs.
411 * @see java.io.FileInputStream#close()
412 */
413 protected void finalize() throws IOException {
414 if (fd != null) {
415 if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
416 flush();
417 } else {
418 /* if fd is shared, the references in FileDescriptor
419 * will ensure that finalizer is only called when
|
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
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).
16 *
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.
20 *
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
23 * questions.
24 */
25
26 package java.io;
27
28 import java.nio.channels.FileChannel;
29 import java.util.concurrent.atomic.AtomicBoolean;
30 import sun.misc.SharedSecrets;
31 import sun.misc.JavaIOFileDescriptorAccess;
32 import sun.nio.ch.FileChannelImpl;
33
34
35 /**
36 * A file output stream is an output stream for writing data to a
37 * <code>File</code> or to a <code>FileDescriptor</code>. Whether or not
38 * a file is available or may be created depends upon the underlying
39 * platform. Some platforms, in particular, allow a file to be opened
40 * for writing by only one <tt>FileOutputStream</tt> (or other
41 * file-writing object) at a time. In such situations the constructors in
42 * this class will fail if the file involved is already open.
43 *
44 * <p><code>FileOutputStream</code> is meant for writing streams of raw bytes
45 * such as image data. For writing streams of characters, consider using
46 * <code>FileWriter</code>.
47 *
48 * @author Arthur van Hoff
49 * @see java.io.File
60 */
61 private static final JavaIOFileDescriptorAccess fdAccess =
62 SharedSecrets.getJavaIOFileDescriptorAccess();
63
64 /**
65 * The system dependent file descriptor.
66 */
67 private final FileDescriptor fd;
68
69 /**
70 * The associated channel, initialized lazily.
71 */
72 private FileChannel channel;
73
74 /**
75 * The path of the referenced file
76 * (null if the stream is created with a file descriptor)
77 */
78 private final String path;
79
80 private AtomicBoolean closed = new AtomicBoolean(false);
81
82 /**
83 * Creates a file output stream to write to the file with the
84 * specified name. A new <code>FileDescriptor</code> object is
85 * created to represent this file connection.
86 * <p>
87 * First, if there is a security manager, its <code>checkWrite</code>
88 * method is called with <code>name</code> as its argument.
89 * <p>
90 * If the file exists but is a directory rather than a regular file, does
91 * not exist but cannot be created, or cannot be opened for any other
92 * reason then a <code>FileNotFoundException</code> is thrown.
93 *
94 * @param name the system-dependent filename
95 * @exception FileNotFoundException if the file exists but is a directory
96 * rather than a regular file, does not exist but cannot
97 * be created, or cannot be opened for any other reason
98 * @exception SecurityException if a security manager exists and its
99 * <code>checkWrite</code> method denies write access
100 * to the file.
324 * @exception IOException if an I/O error occurs.
325 */
326 public void write(byte b[], int off, int len) throws IOException {
327 writeBytes(b, off, len, fdAccess.getAppend(fd));
328 }
329
330 /**
331 * Closes this file output stream and releases any system resources
332 * associated with this stream. This file output stream may no longer
333 * be used for writing bytes.
334 *
335 * <p> If this stream has an associated channel then the channel is closed
336 * as well.
337 *
338 * @exception IOException if an I/O error occurs.
339 *
340 * @revised 1.4
341 * @spec JSR-51
342 */
343 public void close() throws IOException {
344 if (!closed.compareAndSet(false, true)) {
345 // if compareAndSet() returns false closed was already true
346 return;
347 }
348
349 if (channel != null) {
350 channel.close();
351 }
352
353 fd.closeAll(new Closeable() {
354 public void close() throws IOException {
355 close0();
356 }
357 });
358 }
359
360 /**
361 * Returns the file descriptor associated with this stream.
362 *
363 * @return the <code>FileDescriptor</code> object that represents
364 * the connection to the file in the file system being used
365 * by this <code>FileOutputStream</code> object.
366 *
367 * @exception IOException if an I/O error occurs.
378 * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
379 * object associated with this file output stream.
380 *
381 * <p> The initial {@link java.nio.channels.FileChannel#position()
382 * position} of the returned channel will be equal to the
383 * number of bytes written to the file so far unless this stream is in
384 * append mode, in which case it will be equal to the size of the file.
385 * Writing bytes to this stream will increment the channel's position
386 * accordingly. Changing the channel's position, either explicitly or by
387 * writing, will change this stream's file position.
388 *
389 * @return the file channel associated with this file output stream
390 *
391 * @since 1.4
392 * @spec JSR-51
393 */
394 public FileChannel getChannel() {
395 synchronized (this) {
396 if (channel == null) {
397 channel = FileChannelImpl.open(fd, path, false, true, this);
398 if (closed.get()) {
399 try {
400 channel.close();
401 } catch (IOException ioe) {
402 throw new InternalError(ioe); // should not happen
403 }
404 }
405 }
406 return channel;
407 }
408 }
409
410 /**
411 * Cleans up the connection to the file, and ensures that the
412 * <code>close</code> method of this file output stream is
413 * called when there are no more references to this stream.
414 *
415 * @exception IOException if an I/O error occurs.
416 * @see java.io.FileInputStream#close()
417 */
418 protected void finalize() throws IOException {
419 if (fd != null) {
420 if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
421 flush();
422 } else {
423 /* if fd is shared, the references in FileDescriptor
424 * will ensure that finalizer is only called when
|