jtulach@1334: /* jtulach@1334: * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. jtulach@1334: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jtulach@1334: * jtulach@1334: * This code is free software; you can redistribute it and/or modify it jtulach@1334: * under the terms of the GNU General Public License version 2 only, as jtulach@1334: * published by the Free Software Foundation. Oracle designates this jtulach@1334: * particular file as subject to the "Classpath" exception as provided jtulach@1334: * by Oracle in the LICENSE file that accompanied this code. jtulach@1334: * jtulach@1334: * This code is distributed in the hope that it will be useful, but WITHOUT jtulach@1334: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jtulach@1334: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jtulach@1334: * version 2 for more details (a copy is included in the LICENSE file that jtulach@1334: * accompanied this code). jtulach@1334: * jtulach@1334: * You should have received a copy of the GNU General Public License version jtulach@1334: * 2 along with this work; if not, write to the Free Software Foundation, jtulach@1334: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jtulach@1334: * jtulach@1334: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jtulach@1334: * or visit www.oracle.com if you need additional information or have any jtulach@1334: * questions. jtulach@1334: */ jtulach@1334: jtulach@1334: package java.io; jtulach@1334: jtulach@1334: jtulach@1334: jtulach@1334: /** jtulach@1334: * A file output stream is an output stream for writing data to a jtulach@1334: * File or to a FileDescriptor. Whether or not jtulach@1334: * a file is available or may be created depends upon the underlying jtulach@1334: * platform. Some platforms, in particular, allow a file to be opened jtulach@1334: * for writing by only one FileOutputStream (or other jtulach@1334: * file-writing object) at a time. In such situations the constructors in jtulach@1334: * this class will fail if the file involved is already open. jtulach@1334: * jtulach@1334: *

FileOutputStream is meant for writing streams of raw bytes jtulach@1334: * such as image data. For writing streams of characters, consider using jtulach@1334: * FileWriter. jtulach@1334: * jtulach@1334: * @author Arthur van Hoff jtulach@1334: * @see java.io.File jtulach@1334: * @see java.io.FileDescriptor jtulach@1334: * @see java.io.FileInputStream jtulach@1334: * @see java.nio.file.Files#newOutputStream jtulach@1334: * @since JDK1.0 jtulach@1334: */ jtulach@1334: public jtulach@1334: class FileOutputStream extends OutputStream jtulach@1334: { jtulach@1334: /** jtulach@1334: * The system dependent file descriptor. jtulach@1334: */ jtulach@1334: private final FileDescriptor fd; jtulach@1334: jtulach@1334: /** jtulach@1334: * True if the file is opened for append. jtulach@1334: */ jtulach@1334: private final boolean append; jtulach@1334: jtulach@1334: /** jtulach@1334: * The associated channel, initalized lazily. jtulach@1334: */ jaroslav@1337: // private FileChannel channel; jtulach@1334: jtulach@1334: private final Object closeLock = new Object(); jtulach@1334: private volatile boolean closed = false; jtulach@1334: private static final ThreadLocal runningFinalize = jtulach@1334: new ThreadLocal<>(); jtulach@1334: jtulach@1334: private static boolean isRunningFinalize() { jtulach@1334: Boolean val; jtulach@1334: if ((val = runningFinalize.get()) != null) jtulach@1334: return val.booleanValue(); jtulach@1334: return false; jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Creates a file output stream to write to the file with the jtulach@1334: * specified name. A new FileDescriptor object is jtulach@1334: * created to represent this file connection. jtulach@1334: *

jtulach@1334: * First, if there is a security manager, its checkWrite jtulach@1334: * method is called with name as its argument. jtulach@1334: *

jtulach@1334: * If the file exists but is a directory rather than a regular file, does jtulach@1334: * not exist but cannot be created, or cannot be opened for any other jtulach@1334: * reason then a FileNotFoundException is thrown. jtulach@1334: * jtulach@1334: * @param name the system-dependent filename jtulach@1334: * @exception FileNotFoundException if the file exists but is a directory jtulach@1334: * rather than a regular file, does not exist but cannot jtulach@1334: * be created, or cannot be opened for any other reason jtulach@1334: * @exception SecurityException if a security manager exists and its jtulach@1334: * checkWrite method denies write access jtulach@1334: * to the file. jtulach@1334: * @see java.lang.SecurityManager#checkWrite(java.lang.String) jtulach@1334: */ jtulach@1334: public FileOutputStream(String name) throws FileNotFoundException { jtulach@1334: this(name != null ? new File(name) : null, false); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Creates a file output stream to write to the file with the specified jtulach@1334: * name. If the second argument is true, then jtulach@1334: * bytes will be written to the end of the file rather than the beginning. jtulach@1334: * A new FileDescriptor object is created to represent this jtulach@1334: * file connection. jtulach@1334: *

jtulach@1334: * First, if there is a security manager, its checkWrite jtulach@1334: * method is called with name as its argument. jtulach@1334: *

jtulach@1334: * If the file exists but is a directory rather than a regular file, does jtulach@1334: * not exist but cannot be created, or cannot be opened for any other jtulach@1334: * reason then a FileNotFoundException is thrown. jtulach@1334: * jtulach@1334: * @param name the system-dependent file name jtulach@1334: * @param append if true, then bytes will be written jtulach@1334: * to the end of the file rather than the beginning jtulach@1334: * @exception FileNotFoundException if the file exists but is a directory jtulach@1334: * rather than a regular file, does not exist but cannot jtulach@1334: * be created, or cannot be opened for any other reason. jtulach@1334: * @exception SecurityException if a security manager exists and its jtulach@1334: * checkWrite method denies write access jtulach@1334: * to the file. jtulach@1334: * @see java.lang.SecurityManager#checkWrite(java.lang.String) jtulach@1334: * @since JDK1.1 jtulach@1334: */ jtulach@1334: public FileOutputStream(String name, boolean append) jtulach@1334: throws FileNotFoundException jtulach@1334: { jtulach@1334: this(name != null ? new File(name) : null, append); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Creates a file output stream to write to the file represented by jtulach@1334: * the specified File object. A new jtulach@1334: * FileDescriptor object is created to represent this jtulach@1334: * file connection. jtulach@1334: *

jtulach@1334: * First, if there is a security manager, its checkWrite jtulach@1334: * method is called with the path represented by the file jtulach@1334: * argument as its argument. jtulach@1334: *

jtulach@1334: * If the file exists but is a directory rather than a regular file, does jtulach@1334: * not exist but cannot be created, or cannot be opened for any other jtulach@1334: * reason then a FileNotFoundException is thrown. jtulach@1334: * jtulach@1334: * @param file the file to be opened for writing. jtulach@1334: * @exception FileNotFoundException if the file exists but is a directory jtulach@1334: * rather than a regular file, does not exist but cannot jtulach@1334: * be created, or cannot be opened for any other reason jtulach@1334: * @exception SecurityException if a security manager exists and its jtulach@1334: * checkWrite method denies write access jtulach@1334: * to the file. jtulach@1334: * @see java.io.File#getPath() jtulach@1334: * @see java.lang.SecurityException jtulach@1334: * @see java.lang.SecurityManager#checkWrite(java.lang.String) jtulach@1334: */ jtulach@1334: public FileOutputStream(File file) throws FileNotFoundException { jtulach@1334: this(file, false); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Creates a file output stream to write to the file represented by jtulach@1334: * the specified File object. If the second argument is jtulach@1334: * true, then bytes will be written to the end of the file jtulach@1334: * rather than the beginning. A new FileDescriptor object is jtulach@1334: * created to represent this file connection. jtulach@1334: *

jtulach@1334: * First, if there is a security manager, its checkWrite jtulach@1334: * method is called with the path represented by the file jtulach@1334: * argument as its argument. jtulach@1334: *

jtulach@1334: * If the file exists but is a directory rather than a regular file, does jtulach@1334: * not exist but cannot be created, or cannot be opened for any other jtulach@1334: * reason then a FileNotFoundException is thrown. jtulach@1334: * jtulach@1334: * @param file the file to be opened for writing. jtulach@1334: * @param append if true, then bytes will be written jtulach@1334: * to the end of the file rather than the beginning jtulach@1334: * @exception FileNotFoundException if the file exists but is a directory jtulach@1334: * rather than a regular file, does not exist but cannot jtulach@1334: * be created, or cannot be opened for any other reason jtulach@1334: * @exception SecurityException if a security manager exists and its jtulach@1334: * checkWrite method denies write access jtulach@1334: * to the file. jtulach@1334: * @see java.io.File#getPath() jtulach@1334: * @see java.lang.SecurityException jtulach@1334: * @see java.lang.SecurityManager#checkWrite(java.lang.String) jtulach@1334: * @since 1.4 jtulach@1334: */ jtulach@1334: public FileOutputStream(File file, boolean append) jtulach@1334: throws FileNotFoundException jtulach@1334: { jaroslav@1337: throw new SecurityException(); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Creates a file output stream to write to the specified file jtulach@1334: * descriptor, which represents an existing connection to an actual jtulach@1334: * file in the file system. jtulach@1334: *

jtulach@1334: * First, if there is a security manager, its checkWrite jtulach@1334: * method is called with the file descriptor fdObj jtulach@1334: * argument as its argument. jtulach@1334: *

jtulach@1334: * If fdObj is null then a NullPointerException jtulach@1334: * is thrown. jtulach@1334: *

jtulach@1334: * This constructor does not throw an exception if fdObj jtulach@1334: * is {@link java.io.FileDescriptor#valid() invalid}. jtulach@1334: * However, if the methods are invoked on the resulting stream to attempt jtulach@1334: * I/O on the stream, an IOException is thrown. jtulach@1334: * jtulach@1334: * @param fdObj the file descriptor to be opened for writing jtulach@1334: * @exception SecurityException if a security manager exists and its jtulach@1334: * checkWrite method denies jtulach@1334: * write access to the file descriptor jtulach@1334: * @see java.lang.SecurityManager#checkWrite(java.io.FileDescriptor) jtulach@1334: */ jtulach@1334: public FileOutputStream(FileDescriptor fdObj) { jaroslav@1337: throw new SecurityException(); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Opens a file, with the specified name, for overwriting or appending. jtulach@1334: * @param name name of file to be opened jtulach@1334: * @param append whether the file is to be opened in append mode jtulach@1334: */ jtulach@1334: private native void open(String name, boolean append) jtulach@1334: throws FileNotFoundException; jtulach@1334: jtulach@1334: /** jtulach@1334: * Writes the specified byte to this file output stream. jtulach@1334: * jtulach@1334: * @param b the byte to be written. jtulach@1334: * @param append {@code true} if the write operation first jtulach@1334: * advances the position to the end of file jtulach@1334: */ jtulach@1334: private native void write(int b, boolean append) throws IOException; jtulach@1334: jtulach@1334: /** jtulach@1334: * Writes the specified byte to this file output stream. Implements jtulach@1334: * the write method of OutputStream. jtulach@1334: * jtulach@1334: * @param b the byte to be written. jtulach@1334: * @exception IOException if an I/O error occurs. jtulach@1334: */ jtulach@1334: public void write(int b) throws IOException { jtulach@1334: write(b, append); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Writes a sub array as a sequence of bytes. jtulach@1334: * @param b the data to be written jtulach@1334: * @param off the start offset in the data jtulach@1334: * @param len the number of bytes that are written jtulach@1334: * @param append {@code true} to first advance the position to the jtulach@1334: * end of file jtulach@1334: * @exception IOException If an I/O error has occurred. jtulach@1334: */ jtulach@1334: private native void writeBytes(byte b[], int off, int len, boolean append) jtulach@1334: throws IOException; jtulach@1334: jtulach@1334: /** jtulach@1334: * Writes b.length bytes from the specified byte array jtulach@1334: * to this file output stream. jtulach@1334: * jtulach@1334: * @param b the data. jtulach@1334: * @exception IOException if an I/O error occurs. jtulach@1334: */ jtulach@1334: public void write(byte b[]) throws IOException { jtulach@1334: writeBytes(b, 0, b.length, append); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Writes len bytes from the specified byte array jtulach@1334: * starting at offset off to this file output stream. jtulach@1334: * jtulach@1334: * @param b the data. jtulach@1334: * @param off the start offset in the data. jtulach@1334: * @param len the number of bytes to write. jtulach@1334: * @exception IOException if an I/O error occurs. jtulach@1334: */ jtulach@1334: public void write(byte b[], int off, int len) throws IOException { jtulach@1334: writeBytes(b, off, len, append); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Closes this file output stream and releases any system resources jtulach@1334: * associated with this stream. This file output stream may no longer jtulach@1334: * be used for writing bytes. jtulach@1334: * jtulach@1334: *

If this stream has an associated channel then the channel is closed jtulach@1334: * as well. jtulach@1334: * jtulach@1334: * @exception IOException if an I/O error occurs. jtulach@1334: * jtulach@1334: * @revised 1.4 jtulach@1334: * @spec JSR-51 jtulach@1334: */ jtulach@1334: public void close() throws IOException { jtulach@1334: synchronized (closeLock) { jtulach@1334: if (closed) { jtulach@1334: return; jtulach@1334: } jtulach@1334: closed = true; jtulach@1334: } jaroslav@1337: // jaroslav@1337: // if (channel != null) { jaroslav@1337: // /* jaroslav@1337: // * Decrement FD use count associated with the channel jaroslav@1337: // * The use count is incremented whenever a new channel jaroslav@1337: // * is obtained from this stream. jaroslav@1337: // */ jaroslav@1337: // fd.decrementAndGetUseCount(); jaroslav@1337: // channel.close(); jaroslav@1337: // } jtulach@1334: jtulach@1334: /* jtulach@1334: * Decrement FD use count associated with this stream jtulach@1334: */ jtulach@1334: int useCount = fd.decrementAndGetUseCount(); jtulach@1334: jtulach@1334: /* jtulach@1334: * If FileDescriptor is still in use by another stream, the finalizer jtulach@1334: * will not close it. jtulach@1334: */ jtulach@1334: if ((useCount <= 0) || !isRunningFinalize()) { jtulach@1334: close0(); jtulach@1334: } jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns the file descriptor associated with this stream. jtulach@1334: * jtulach@1334: * @return the FileDescriptor object that represents jtulach@1334: * the connection to the file in the file system being used jtulach@1334: * by this FileOutputStream object. jtulach@1334: * jtulach@1334: * @exception IOException if an I/O error occurs. jtulach@1334: * @see java.io.FileDescriptor jtulach@1334: */ jtulach@1334: public final FileDescriptor getFD() throws IOException { jtulach@1334: if (fd != null) return fd; jtulach@1334: throw new IOException(); jtulach@1334: } jtulach@1334: jtulach@1334: /** jtulach@1334: * Returns the unique {@link java.nio.channels.FileChannel FileChannel} jtulach@1334: * object associated with this file output stream.

jtulach@1334: * jtulach@1334: *

The initial {@link java.nio.channels.FileChannel#position() jtulach@1334: * position} of the returned channel will be equal to the jtulach@1334: * number of bytes written to the file so far unless this stream is in jtulach@1334: * append mode, in which case it will be equal to the size of the file. jtulach@1334: * Writing bytes to this stream will increment the channel's position jtulach@1334: * accordingly. Changing the channel's position, either explicitly or by jtulach@1334: * writing, will change this stream's file position. jtulach@1334: * jtulach@1334: * @return the file channel associated with this file output stream jtulach@1334: * jtulach@1334: * @since 1.4 jtulach@1334: * @spec JSR-51 jtulach@1334: */ jaroslav@1337: // public FileChannel getChannel() { jaroslav@1337: // synchronized (this) { jaroslav@1337: // if (channel == null) { jaroslav@1337: // channel = FileChannelImpl.open(fd, false, true, append, this); jaroslav@1337: // jaroslav@1337: // /* jaroslav@1337: // * Increment fd's use count. Invoking the channel's close() jaroslav@1337: // * method will result in decrementing the use count set for jaroslav@1337: // * the channel. jaroslav@1337: // */ jaroslav@1337: // fd.incrementAndGetUseCount(); jaroslav@1337: // } jaroslav@1337: // return channel; jaroslav@1337: // } jaroslav@1337: // } jtulach@1334: jtulach@1334: /** jtulach@1334: * Cleans up the connection to the file, and ensures that the jtulach@1334: * close method of this file output stream is jtulach@1334: * called when there are no more references to this stream. jtulach@1334: * jtulach@1334: * @exception IOException if an I/O error occurs. jtulach@1334: * @see java.io.FileInputStream#close() jtulach@1334: */ jtulach@1334: protected void finalize() throws IOException { jtulach@1334: if (fd != null) { jtulach@1334: if (fd == FileDescriptor.out || fd == FileDescriptor.err) { jtulach@1334: flush(); jtulach@1334: } else { jtulach@1334: jtulach@1334: /* jtulach@1334: * Finalizer should not release the FileDescriptor if another jtulach@1334: * stream is still using it. If the user directly invokes jtulach@1334: * close() then the FileDescriptor is also released. jtulach@1334: */ jtulach@1334: runningFinalize.set(Boolean.TRUE); jtulach@1334: try { jtulach@1334: close(); jtulach@1334: } finally { jtulach@1334: runningFinalize.set(Boolean.FALSE); jtulach@1334: } jtulach@1334: } jtulach@1334: } jtulach@1334: } jtulach@1334: jtulach@1334: private native void close0() throws IOException; jtulach@1334: jtulach@1334: private static native void initIDs(); jtulach@1334: jtulach@1334: static { jtulach@1334: initIDs(); jtulach@1334: } jtulach@1334: jtulach@1334: }