Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6378948

BufferedWriter.close() doesn't close underlying Writer if flushBuffer() throws IOException

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 5.0
    • core-libs
    • x86
    • windows_xp

      FULL PRODUCT VERSION :
      java version "1.4.2"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.
      Java HotSpot(TM) Client VM (build 1.4.2-b28, mixed mode)

      FULL OS VERSION :
      Microsoft Windows XP [Version 5.1.2600]

      A DESCRIPTION OF THE PROBLEM :
      If a BufferedWriter is used to write to a file, and an IOException occurs during the flush call in BufferedWriter.close(), then the file will not be closed.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Create a floppy disk with little (e.g., 1K) free disk space.
      Run the attached program.
      When prompted, specify the name for a new file on the floppy disk.
      The program should display the message "Closing the writer." on standard error, then display a dialog instructing you to try to delete the file.
      Try to delete the file.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      You should be able to delete the file, BufferedWriter.close() was called.
      ACTUAL -
      You cannot delete the file.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.io.*;
      import javax.swing.*;

      /**
       * This program illustrates that some writers, such as BufferedWriter and
       * OutputStreamWriter, don't close the underlying Writer or OutputStream if an
       * exception is thrown during the close operation.
       *
       * The works by determining the number of strings that need to be written to
       * a file on a given directory in order for a flush operation to throw an
       * IOException. It then uses the standard approach of wrapping a FileWriter in
       * a BufferedWriter to write the file. After writing the file, the BufferedWriter
       * is closed. The program then displays a dialog that asks to user to verify
       * that the file is still open by trying to delete the file.
       *
       * The program determines the number of strings that need to be written by
       * writing strings to a temporary file in the target directory. Once it has
       * written enough strings to cause an IOException, it closes and deletes the
       * file. The approach used to create this file is to wrap a FileOutputStream
       * in an OutputStreamWriter and BufferedWriter. Closing the FileOutputStream
       * actually closes the underlying file, which allows it to be deleted. This
       * approach provides a workaround for the defect.
       */
      public class CloseFailure
      {
        public static void main (String[] args)
        {
          JFileChooser chooser = new JFileChooser();
          
          chooser.setDialogTitle ("Specify a file on a floppy disk with little free space.");
          if (chooser.showSaveDialog (null) != JFileChooser.APPROVE_OPTION)
            return;
          
          File file = chooser.getSelectedFile();
          int nWrites = determineWritesRequired (file.getParentFile());
          Writer writer = null;
          
          try
          {
            writer = new BufferedWriter (new FileWriter (file));
            writeNStrings (writer, nWrites);
            System.err.println ("Closing the writer.");
            writer.close();
            
          } catch (IOException ioe) {
            JOptionPane.showMessageDialog (null,
              "You can verify that the file is still open\nby trying to delete it.");
          } finally {
            System.exit (0);
          } // try
        } // main
        
        private static final String SOME_STRING =
          "This program illustrates a defect in the implementation of BufferedWriter.close().\n";
        
        /**
         * Return the number of SOME_STRINGs that need to be written to the
         * given directory to cause an IOException when the writer is flushed.
         */
        private static int determineWritesRequired (File directory)
        {
          File file = null;
          OutputStream stream = null;
          Writer writer = null;
          int result = 0;
          
          try
          {
            file = File.createTempFile ("Temp", ".txt", directory);
            stream = new FileOutputStream (file);
            writer = new BufferedWriter (new OutputStreamWriter (stream));
            
            while (true)
            {
              ++result;
              writer.write (SOME_STRING);
              writer.flush();
            } // while
            
          } catch (IOException ioe) {
            try
            {
              stream.close();
              file.delete();
            } catch (IOException e) {
              e.printStackTrace();
            } // try
          } // try
          
          return result;
        } // determineWritesRequired
        
        /**
         * Write n SOME_STRINGS to the given Writer.
         */
        private static void writeNStrings (Writer writer, int n) throws IOException
        {
          try
          {
            for (int i = 0; i < n; ++i)
              writer.write (SOME_STRING);
            
          } catch (IOException e) {
            System.err.println ("We didn't get the number of writes correct.");
          } // try
        } // writeSomeStuff
      } // CloseFailure
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Wrap a FileOutputStream in an OutputStreamWriter instead of using a FileWriter and close the FileOutputStream if there is an exception writing to or closing the Writer.

            iris Iris Clark
            gmanwanisunw Girish Manwani (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: