Save This Page
Home » openjdk-7 » java » io » [javadoc | source]
    1   /*
    2    * Copyright 1994-2007 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    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.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package java.io;
   27   
   28   import java.nio.channels.FileChannel;
   29   import sun.nio.ch.FileChannelImpl;
   30   
   31   
   32   /**
   33    * A file output stream is an output stream for writing data to a
   34    * <code>File</code> or to a <code>FileDescriptor</code>. Whether or not
   35    * a file is available or may be created depends upon the underlying
   36    * platform.  Some platforms, in particular, allow a file to be opened
   37    * for writing by only one <tt>FileOutputStream</tt> (or other
   38    * file-writing object) at a time.  In such situations the constructors in
   39    * this class will fail if the file involved is already open.
   40    *
   41    * <p><code>FileOutputStream</code> is meant for writing streams of raw bytes
   42    * such as image data. For writing streams of characters, consider using
   43    * <code>FileWriter</code>.
   44    *
   45    * @author  Arthur van Hoff
   46    * @see     java.io.File
   47    * @see     java.io.FileDescriptor
   48    * @see     java.io.FileInputStream
   49    * @since   JDK1.0
   50    */
   51   public
   52   class FileOutputStream extends OutputStream
   53   {
   54       /**
   55        * The system dependent file descriptor.
   56        */
   57       private final FileDescriptor fd;
   58   
   59       private FileChannel channel= null;
   60   
   61       private final Object closeLock = new Object();
   62       private volatile boolean closed = false;
   63       private static final ThreadLocal<Boolean> runningFinalize =
   64           new ThreadLocal<Boolean>();
   65   
   66       private static boolean isRunningFinalize() {
   67           Boolean val;
   68           if ((val = runningFinalize.get()) != null)
   69               return val.booleanValue();
   70           return false;
   71       }
   72   
   73       /**
   74        * Creates a file output stream to write to the file with the
   75        * specified name. A new <code>FileDescriptor</code> object is
   76        * created to represent this file connection.
   77        * <p>
   78        * First, if there is a security manager, its <code>checkWrite</code>
   79        * method is called with <code>name</code> as its argument.
   80        * <p>
   81        * If the file exists but is a directory rather than a regular file, does
   82        * not exist but cannot be created, or cannot be opened for any other
   83        * reason then a <code>FileNotFoundException</code> is thrown.
   84        *
   85        * @param      name   the system-dependent filename
   86        * @exception  FileNotFoundException  if the file exists but is a directory
   87        *                   rather than a regular file, does not exist but cannot
   88        *                   be created, or cannot be opened for any other reason
   89        * @exception  SecurityException  if a security manager exists and its
   90        *               <code>checkWrite</code> method denies write access
   91        *               to the file.
   92        * @see        java.lang.SecurityManager#checkWrite(java.lang.String)
   93        */
   94       public FileOutputStream(String name) throws FileNotFoundException {
   95           this(name != null ? new File(name) : null, false);
   96       }
   97   
   98       /**
   99        * Creates a file output stream to write to the file with the specified
  100        * name.  If the second argument is <code>true</code>, then
  101        * bytes will be written to the end of the file rather than the beginning.
  102        * A new <code>FileDescriptor</code> object is created to represent this
  103        * file connection.
  104        * <p>
  105        * First, if there is a security manager, its <code>checkWrite</code>
  106        * method is called with <code>name</code> as its argument.
  107        * <p>
  108        * If the file exists but is a directory rather than a regular file, does
  109        * not exist but cannot be created, or cannot be opened for any other
  110        * reason then a <code>FileNotFoundException</code> is thrown.
  111        *
  112        * @param     name        the system-dependent file name
  113        * @param     append      if <code>true</code>, then bytes will be written
  114        *                   to the end of the file rather than the beginning
  115        * @exception  FileNotFoundException  if the file exists but is a directory
  116        *                   rather than a regular file, does not exist but cannot
  117        *                   be created, or cannot be opened for any other reason.
  118        * @exception  SecurityException  if a security manager exists and its
  119        *               <code>checkWrite</code> method denies write access
  120        *               to the file.
  121        * @see        java.lang.SecurityManager#checkWrite(java.lang.String)
  122        * @since     JDK1.1
  123        */
  124       public FileOutputStream(String name, boolean append)
  125           throws FileNotFoundException
  126       {
  127           this(name != null ? new File(name) : null, append);
  128       }
  129   
  130       /**
  131        * Creates a file output stream to write to the file represented by
  132        * the specified <code>File</code> object. A new
  133        * <code>FileDescriptor</code> object is created to represent this
  134        * file connection.
  135        * <p>
  136        * First, if there is a security manager, its <code>checkWrite</code>
  137        * method is called with the path represented by the <code>file</code>
  138        * argument as its argument.
  139        * <p>
  140        * If the file exists but is a directory rather than a regular file, does
  141        * not exist but cannot be created, or cannot be opened for any other
  142        * reason then a <code>FileNotFoundException</code> is thrown.
  143        *
  144        * @param      file               the file to be opened for writing.
  145        * @exception  FileNotFoundException  if the file exists but is a directory
  146        *                   rather than a regular file, does not exist but cannot
  147        *                   be created, or cannot be opened for any other reason
  148        * @exception  SecurityException  if a security manager exists and its
  149        *               <code>checkWrite</code> method denies write access
  150        *               to the file.
  151        * @see        java.io.File#getPath()
  152        * @see        java.lang.SecurityException
  153        * @see        java.lang.SecurityManager#checkWrite(java.lang.String)
  154        */
  155       public FileOutputStream(File file) throws FileNotFoundException {
  156           this(file, false);
  157       }
  158   
  159       /**
  160        * Creates a file output stream to write to the file represented by
  161        * the specified <code>File</code> object. If the second argument is
  162        * <code>true</code>, then bytes will be written to the end of the file
  163        * rather than the beginning. A new <code>FileDescriptor</code> object is
  164        * created to represent this file connection.
  165        * <p>
  166        * First, if there is a security manager, its <code>checkWrite</code>
  167        * method is called with the path represented by the <code>file</code>
  168        * argument as its argument.
  169        * <p>
  170        * If the file exists but is a directory rather than a regular file, does
  171        * not exist but cannot be created, or cannot be opened for any other
  172        * reason then a <code>FileNotFoundException</code> is thrown.
  173        *
  174        * @param      file               the file to be opened for writing.
  175        * @param     append      if <code>true</code>, then bytes will be written
  176        *                   to the end of the file rather than the beginning
  177        * @exception  FileNotFoundException  if the file exists but is a directory
  178        *                   rather than a regular file, does not exist but cannot
  179        *                   be created, or cannot be opened for any other reason
  180        * @exception  SecurityException  if a security manager exists and its
  181        *               <code>checkWrite</code> method denies write access
  182        *               to the file.
  183        * @see        java.io.File#getPath()
  184        * @see        java.lang.SecurityException
  185        * @see        java.lang.SecurityManager#checkWrite(java.lang.String)
  186        * @since 1.4
  187        */
  188       public FileOutputStream(File file, boolean append)
  189           throws FileNotFoundException
  190       {
  191           String name = (file != null ? file.getPath() : null);
  192           SecurityManager security = System.getSecurityManager();
  193           if (security != null) {
  194               security.checkWrite(name);
  195           }
  196           if (name == null) {
  197               throw new NullPointerException();
  198           }
  199           fd = new FileDescriptor();
  200           fd.incrementAndGetUseCount();
  201           open(name, append);
  202       }
  203   
  204       /**
  205        * Creates a file output stream to write to the specified file
  206        * descriptor, which represents an existing connection to an actual
  207        * file in the file system.
  208        * <p>
  209        * First, if there is a security manager, its <code>checkWrite</code>
  210        * method is called with the file descriptor <code>fdObj</code>
  211        * argument as its argument.
  212        * <p>
  213        * If <code>fdObj</code> is null then a <code>NullPointerException</code>
  214        * is thrown.
  215        * <p>
  216        * This constructor does not throw an exception if <code>fdObj</code>
  217        * is {@link java.io.FileDescriptor#valid() invalid}.
  218        * However, if the methods are invoked on the resulting stream to attempt
  219        * I/O on the stream, an <code>IOException</code> is thrown.
  220        *
  221        * @param      fdObj   the file descriptor to be opened for writing
  222        * @exception  SecurityException  if a security manager exists and its
  223        *               <code>checkWrite</code> method denies
  224        *               write access to the file descriptor
  225        * @see        java.lang.SecurityManager#checkWrite(java.io.FileDescriptor)
  226        */
  227       public FileOutputStream(FileDescriptor fdObj) {
  228           SecurityManager security = System.getSecurityManager();
  229           if (fdObj == null) {
  230               throw new NullPointerException();
  231           }
  232           if (security != null) {
  233               security.checkWrite(fdObj);
  234           }
  235           fd = fdObj;
  236   
  237           /*
  238            * FileDescriptor is being shared by streams.
  239            * Ensure that it's GC'ed only when all the streams/channels are done
  240            * using it.
  241            */
  242           fd.incrementAndGetUseCount();
  243       }
  244   
  245       /**
  246        * Opens a file, with the specified name, for overwriting or appending.
  247        * @param name name of file to be opened
  248        * @param append whether the file is to be opened in append mode
  249        */
  250       private native void open(String name, boolean append)
  251           throws FileNotFoundException;
  252   
  253       /**
  254        * Writes the specified byte to this file output stream. Implements
  255        * the <code>write</code> method of <code>OutputStream</code>.
  256        *
  257        * @param      b   the byte to be written.
  258        * @exception  IOException  if an I/O error occurs.
  259        */
  260       public native void write(int b) throws IOException;
  261   
  262       /**
  263        * Writes a sub array as a sequence of bytes.
  264        * @param b the data to be written
  265        * @param off the start offset in the data
  266        * @param len the number of bytes that are written
  267        * @exception IOException If an I/O error has occurred.
  268        */
  269       private native void writeBytes(byte b[], int off, int len) throws IOException;
  270   
  271       /**
  272        * Writes <code>b.length</code> bytes from the specified byte array
  273        * to this file output stream.
  274        *
  275        * @param      b   the data.
  276        * @exception  IOException  if an I/O error occurs.
  277        */
  278       public void write(byte b[]) throws IOException {
  279           writeBytes(b, 0, b.length);
  280       }
  281   
  282       /**
  283        * Writes <code>len</code> bytes from the specified byte array
  284        * starting at offset <code>off</code> to this file output stream.
  285        *
  286        * @param      b     the data.
  287        * @param      off   the start offset in the data.
  288        * @param      len   the number of bytes to write.
  289        * @exception  IOException  if an I/O error occurs.
  290        */
  291       public void write(byte b[], int off, int len) throws IOException {
  292           writeBytes(b, off, len);
  293       }
  294   
  295       /**
  296        * Closes this file output stream and releases any system resources
  297        * associated with this stream. This file output stream may no longer
  298        * be used for writing bytes.
  299        *
  300        * <p> If this stream has an associated channel then the channel is closed
  301        * as well.
  302        *
  303        * @exception  IOException  if an I/O error occurs.
  304        *
  305        * @revised 1.4
  306        * @spec JSR-51
  307        */
  308       public void close() throws IOException {
  309           synchronized (closeLock) {
  310               if (closed) {
  311                   return;
  312               }
  313               closed = true;
  314           }
  315   
  316           if (channel != null) {
  317               /*
  318                * Decrement FD use count associated with the channel
  319                * The use count is incremented whenever a new channel
  320                * is obtained from this stream.
  321                */
  322               fd.decrementAndGetUseCount();
  323               channel.close();
  324           }
  325   
  326           /*
  327            * Decrement FD use count associated with this stream
  328            */
  329           int useCount = fd.decrementAndGetUseCount();
  330   
  331           /*
  332            * If FileDescriptor is still in use by another stream, the finalizer
  333            * will not close it.
  334            */
  335           if ((useCount <= 0) || !isRunningFinalize()) {
  336               close0();
  337           }
  338       }
  339   
  340       /**
  341        * Returns the file descriptor associated with this stream.
  342        *
  343        * @return  the <code>FileDescriptor</code> object that represents
  344        *          the connection to the file in the file system being used
  345        *          by this <code>FileOutputStream</code> object.
  346        *
  347        * @exception  IOException  if an I/O error occurs.
  348        * @see        java.io.FileDescriptor
  349        */
  350        public final FileDescriptor getFD()  throws IOException {
  351           if (fd != null) return fd;
  352           throw new IOException();
  353        }
  354   
  355       /**
  356        * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
  357        * object associated with this file output stream. </p>
  358        *
  359        * <p> The initial {@link java.nio.channels.FileChannel#position()
  360        * </code>position<code>} of the returned channel will be equal to the
  361        * number of bytes written to the file so far unless this stream is in
  362        * append mode, in which case it will be equal to the size of the file.
  363        * Writing bytes to this stream will increment the channel's position
  364        * accordingly.  Changing the channel's position, either explicitly or by
  365        * writing, will change this stream's file position.
  366        *
  367        * @return  the file channel associated with this file output stream
  368        *
  369        * @since 1.4
  370        * @spec JSR-51
  371        */
  372       public FileChannel getChannel() {
  373           synchronized (this) {
  374               if (channel == null) {
  375                   channel = FileChannelImpl.open(fd, false, true, this);
  376   
  377                   /*
  378                    * Increment fd's use count. Invoking the channel's close()
  379                    * method will result in decrementing the use count set for
  380                    * the channel.
  381                    */
  382                   fd.incrementAndGetUseCount();
  383               }
  384               return channel;
  385           }
  386       }
  387   
  388       /**
  389        * Cleans up the connection to the file, and ensures that the
  390        * <code>close</code> method of this file output stream is
  391        * called when there are no more references to this stream.
  392        *
  393        * @exception  IOException  if an I/O error occurs.
  394        * @see        java.io.FileInputStream#close()
  395        */
  396       protected void finalize() throws IOException {
  397           if (fd != null) {
  398               if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
  399                   flush();
  400               } else {
  401   
  402                   /*
  403                    * Finalizer should not release the FileDescriptor if another
  404                    * stream is still using it. If the user directly invokes
  405                    * close() then the FileDescriptor is also released.
  406                    */
  407                   runningFinalize.set(Boolean.TRUE);
  408                   try {
  409                       close();
  410                   } finally {
  411                       runningFinalize.set(Boolean.FALSE);
  412                   }
  413               }
  414           }
  415       }
  416   
  417       private native void close0() throws IOException;
  418   
  419       private static native void initIDs();
  420   
  421       static {
  422           initIDs();
  423       }
  424   
  425   }

Save This Page
Home » openjdk-7 » java » io » [javadoc | source]