src/share/classes/java/io/FileOutputStream.java

Print this page




  52 public
  53 class FileOutputStream extends OutputStream
  54 {
  55     /**
  56      * The system dependent file descriptor.
  57      */
  58     private final FileDescriptor fd;
  59 
  60     /**
  61      * True if the file is opened for append.
  62      */
  63     private final boolean append;
  64 
  65     /**
  66      * The associated channel, initalized lazily.
  67      */
  68     private FileChannel channel;
  69 
  70     private final Object closeLock = new Object();
  71     private volatile boolean closed = false;


  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)


 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         this.fd = new FileDescriptor();
 200         this.append = append;
 201 
 202         fd.attach(this);
 203         open(name, append);
 204     }
 205 
 206     /**
 207      * Creates a file output stream to write to the specified file
 208      * descriptor, which represents an existing connection to an actual
 209      * file in the file system.
 210      * <p>
 211      * First, if there is a security manager, its <code>checkWrite</code>
 212      * method is called with the file descriptor <code>fdObj</code>
 213      * argument as its argument.
 214      * <p>
 215      * If <code>fdObj</code> is null then a <code>NullPointerException</code>
 216      * is thrown.
 217      * <p>
 218      * This constructor does not throw an exception if <code>fdObj</code>
 219      * is {@link java.io.FileDescriptor#valid() invalid}.
 220      * However, if the methods are invoked on the resulting stream to attempt
 221      * I/O on the stream, an <code>IOException</code> is thrown.
 222      *
 223      * @param      fdObj   the file descriptor to be opened for writing
 224      * @exception  SecurityException  if a security manager exists and its
 225      *               <code>checkWrite</code> method denies
 226      *               write access to the file descriptor
 227      * @see        java.lang.SecurityManager#checkWrite(java.io.FileDescriptor)
 228      */
 229     public FileOutputStream(FileDescriptor fdObj) {
 230         SecurityManager security = System.getSecurityManager();
 231         if (fdObj == null) {
 232             throw new NullPointerException();
 233         }
 234         if (security != null) {
 235             security.checkWrite(fdObj);
 236         }
 237         this.fd = fdObj;
 238         this.append = false;
 239         fd.attach(this);






 240     }
 241 
 242     /**
 243      * Opens a file, with the specified name, for overwriting or appending.
 244      * @param name name of file to be opened
 245      * @param append whether the file is to be opened in append mode
 246      */
 247     private native void open(String name, boolean append)
 248         throws FileNotFoundException;
 249 
 250     /**
 251      * Writes the specified byte to this file output stream.
 252      *
 253      * @param   b   the byte to be written.
 254      * @param   append   {@code true} if the write operation first
 255      *     advances the position to the end of file
 256      */
 257     private native void write(int b, boolean append) throws IOException;
 258 
 259     /**


 308      * associated with this stream. This file output stream may no longer
 309      * be used for writing bytes.
 310      *
 311      * <p> If this stream has an associated channel then the channel is closed
 312      * as well.
 313      *
 314      * @exception  IOException  if an I/O error occurs.
 315      *
 316      * @revised 1.4
 317      * @spec JSR-51
 318      */
 319     public void close() throws IOException {
 320         synchronized (closeLock) {
 321             if (closed) {
 322                 return;
 323             }
 324             closed = true;
 325         }
 326 
 327         if (channel != null) {






 328             channel.close();
 329         }
 330         fd.closeAll(new Closeable() {
 331             public void close() throws IOException {









 332                close0();
 333            }
 334         });
 335     }
 336 
 337     /**
 338      * Returns the file descriptor associated with this stream.
 339      *
 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.
 343      *
 344      * @exception  IOException  if an I/O error occurs.
 345      * @see        java.io.FileDescriptor
 346      */
 347      public final FileDescriptor getFD()  throws IOException {
 348         if (fd != null) {
 349             return fd;
 350         }
 351         throw new IOException();
 352      }
 353 
 354     /**
 355      * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
 356      * object associated with this file output stream. </p>
 357      *
 358      * <p> The initial {@link java.nio.channels.FileChannel#position()
 359      * </code>position<code>} of the returned channel will be equal to the
 360      * number of bytes written to the file so far unless this stream is in
 361      * append mode, in which case it will be equal to the size of the file.
 362      * Writing bytes to this stream will increment the channel's position
 363      * accordingly.  Changing the channel's position, either explicitly or by
 364      * writing, will change this stream's file position.
 365      *
 366      * @return  the file channel associated with this file output stream
 367      *
 368      * @since 1.4
 369      * @spec JSR-51
 370      */
 371     public FileChannel getChannel() {
 372         synchronized (this) {
 373             if (channel == null) {
 374                 channel = FileChannelImpl.open(fd, false, true, append, this);







 375             }
 376             return channel;
 377         }
 378     }
 379 
 380     /**
 381      * Cleans up the connection to the file, and ensures that the
 382      * <code>close</code> method of this file output stream is
 383      * called when there are no more references to this stream.
 384      *
 385      * @exception  IOException  if an I/O error occurs.
 386      * @see        java.io.FileInputStream#close()
 387      */
 388     protected void finalize() throws IOException {
 389         if (fd != null) {
 390             if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
 391                 flush();
 392             } else {
 393                 /* if fd is shared, the references in FileDescriptor
 394                  * will ensure that finalizer is only called when
 395                  * safe to do so. All references using the fd have
 396                  * become unreachable. We can call close()

 397                  */


 398                 close();


 399             }
 400         }

 401     }
 402 
 403     private native void close0() throws IOException;
 404 
 405     private static native void initIDs();
 406 
 407     static {
 408         initIDs();
 409     }
 410 
 411 }


  52 public
  53 class FileOutputStream extends OutputStream
  54 {
  55     /**
  56      * The system dependent file descriptor.
  57      */
  58     private final FileDescriptor fd;
  59 
  60     /**
  61      * True if the file is opened for append.
  62      */
  63     private final boolean append;
  64 
  65     /**
  66      * The associated channel, initalized lazily.
  67      */
  68     private FileChannel channel;
  69 
  70     private final Object closeLock = new Object();
  71     private volatile boolean closed = false;
  72     private static final ThreadLocal<Boolean> runningFinalize =
  73         new ThreadLocal<>();
  74 
  75     private static boolean isRunningFinalize() {
  76         Boolean val;
  77         if ((val = runningFinalize.get()) != null)
  78             return val.booleanValue();
  79         return false;
  80     }
  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.
 101      * @see        java.lang.SecurityManager#checkWrite(java.lang.String)


 191      *               to the file.
 192      * @see        java.io.File#getPath()
 193      * @see        java.lang.SecurityException
 194      * @see        java.lang.SecurityManager#checkWrite(java.lang.String)
 195      * @since 1.4
 196      */
 197     public FileOutputStream(File file, boolean append)
 198         throws FileNotFoundException
 199     {
 200         String name = (file != null ? file.getPath() : null);
 201         SecurityManager security = System.getSecurityManager();
 202         if (security != null) {
 203             security.checkWrite(name);
 204         }
 205         if (name == null) {
 206             throw new NullPointerException();
 207         }
 208         this.fd = new FileDescriptor();
 209         this.append = append;
 210 
 211         fd.incrementAndGetUseCount();
 212         open(name, append);
 213     }
 214 
 215     /**
 216      * Creates a file output stream to write to the specified file
 217      * descriptor, which represents an existing connection to an actual
 218      * file in the file system.
 219      * <p>
 220      * First, if there is a security manager, its <code>checkWrite</code>
 221      * method is called with the file descriptor <code>fdObj</code>
 222      * argument as its argument.
 223      * <p>
 224      * If <code>fdObj</code> is null then a <code>NullPointerException</code>
 225      * is thrown.
 226      * <p>
 227      * This constructor does not throw an exception if <code>fdObj</code>
 228      * is {@link java.io.FileDescriptor#valid() invalid}.
 229      * However, if the methods are invoked on the resulting stream to attempt
 230      * I/O on the stream, an <code>IOException</code> is thrown.
 231      *
 232      * @param      fdObj   the file descriptor to be opened for writing
 233      * @exception  SecurityException  if a security manager exists and its
 234      *               <code>checkWrite</code> method denies
 235      *               write access to the file descriptor
 236      * @see        java.lang.SecurityManager#checkWrite(java.io.FileDescriptor)
 237      */
 238     public FileOutputStream(FileDescriptor fdObj) {
 239         SecurityManager security = System.getSecurityManager();
 240         if (fdObj == null) {
 241             throw new NullPointerException();
 242         }
 243         if (security != null) {
 244             security.checkWrite(fdObj);
 245         }
 246         this.fd = fdObj;
 247         this.append = false;
 248 
 249         /*
 250          * FileDescriptor is being shared by streams.
 251          * Ensure that it's GC'ed only when all the streams/channels are done
 252          * using it.
 253          */
 254         fd.incrementAndGetUseCount();
 255     }
 256 
 257     /**
 258      * Opens a file, with the specified name, for overwriting or appending.
 259      * @param name name of file to be opened
 260      * @param append whether the file is to be opened in append mode
 261      */
 262     private native void open(String name, boolean append)
 263         throws FileNotFoundException;
 264 
 265     /**
 266      * Writes the specified byte to this file output stream.
 267      *
 268      * @param   b   the byte to be written.
 269      * @param   append   {@code true} if the write operation first
 270      *     advances the position to the end of file
 271      */
 272     private native void write(int b, boolean append) throws IOException;
 273 
 274     /**


 323      * associated with this stream. This file output stream may no longer
 324      * be used for writing bytes.
 325      *
 326      * <p> If this stream has an associated channel then the channel is closed
 327      * as well.
 328      *
 329      * @exception  IOException  if an I/O error occurs.
 330      *
 331      * @revised 1.4
 332      * @spec JSR-51
 333      */
 334     public void close() throws IOException {
 335         synchronized (closeLock) {
 336             if (closed) {
 337                 return;
 338             }
 339             closed = true;
 340         }
 341 
 342         if (channel != null) {
 343             /*
 344              * Decrement FD use count associated with the channel
 345              * The use count is incremented whenever a new channel
 346              * is obtained from this stream.
 347              */
 348             fd.decrementAndGetUseCount();
 349             channel.close();
 350         }
 351 
 352         /*
 353          * Decrement FD use count associated with this stream
 354          */
 355         int useCount = fd.decrementAndGetUseCount();
 356 
 357         /*
 358          * If FileDescriptor is still in use by another stream, the finalizer
 359          * will not close it.
 360          */
 361         if ((useCount <= 0) || !isRunningFinalize()) {
 362             close0();
 363         }

 364     }
 365 
 366     /**
 367      * Returns the file descriptor associated with this stream.
 368      *
 369      * @return  the <code>FileDescriptor</code> object that represents
 370      *          the connection to the file in the file system being used
 371      *          by this <code>FileOutputStream</code> object.
 372      *
 373      * @exception  IOException  if an I/O error occurs.
 374      * @see        java.io.FileDescriptor
 375      */
 376      public final FileDescriptor getFD()  throws IOException {
 377         if (fd != null) return fd;


 378         throw new IOException();
 379      }
 380 
 381     /**
 382      * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
 383      * object associated with this file output stream. </p>
 384      *
 385      * <p> The initial {@link java.nio.channels.FileChannel#position()
 386      * </code>position<code>} of the returned channel will be equal to the
 387      * number of bytes written to the file so far unless this stream is in
 388      * append mode, in which case it will be equal to the size of the file.
 389      * Writing bytes to this stream will increment the channel's position
 390      * accordingly.  Changing the channel's position, either explicitly or by
 391      * writing, will change this stream's file position.
 392      *
 393      * @return  the file channel associated with this file output stream
 394      *
 395      * @since 1.4
 396      * @spec JSR-51
 397      */
 398     public FileChannel getChannel() {
 399         synchronized (this) {
 400             if (channel == null) {
 401                 channel = FileChannelImpl.open(fd, false, true, append, this);
 402 
 403                 /*
 404                  * Increment fd's use count. Invoking the channel's close()
 405                  * method will result in decrementing the use count set for
 406                  * the channel.
 407                  */
 408                 fd.incrementAndGetUseCount();
 409             }
 410             return channel;
 411         }
 412     }
 413 
 414     /**
 415      * Cleans up the connection to the file, and ensures that the
 416      * <code>close</code> method of this file output stream is
 417      * called when there are no more references to this stream.
 418      *
 419      * @exception  IOException  if an I/O error occurs.
 420      * @see        java.io.FileInputStream#close()
 421      */
 422     protected void finalize() throws IOException {
 423         if (fd != null) {
 424             if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
 425                 flush();
 426             } else {
 427 
 428                 /*
 429                  * Finalizer should not release the FileDescriptor if another
 430                  * stream is still using it. If the user directly invokes
 431                  * close() then the FileDescriptor is also released.
 432                  */
 433                 runningFinalize.set(Boolean.TRUE);
 434                 try {
 435                     close();
 436                 } finally {
 437                     runningFinalize.set(Boolean.FALSE);
 438                 }
 439             }
 440         }
 441     }
 442 
 443     private native void close0() throws IOException;
 444 
 445     private static native void initIDs();
 446 
 447     static {
 448         initIDs();
 449     }
 450 
 451 }