-2

I noticed that if I don't call myBufferedWriter.close(), my content will not appear in the target file. What if the program ends accidentally before reaching myBufferedWriter.close()? How to avoid losing data that are already in the buffer but not written to the file yet?

Edit: I have found the simple use case of try-with-resources, but my code is like the following

public class myClass{
    Map<String, BufferedWriter> writerMap = new HashMap<>();
    public void write(···){
        //call this.create() here
        ···
        //normally, the writer will close here

    }
    
    public void create(···){
        //BufferedWriter is created here, and saved into writerMap
        ···
    }


}

Where is the best place to use the try-with-resources statement?

  • 1
    Use `try-with-resources` : https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html – Rob Audenaerde Jun 13 '22 at 07:37
  • You can call `flush()` occasionally to reduce the duration of writes that may be lost. – tgdavies Jun 13 '22 at 07:49
  • You can also create your BufferedWriter with a smaller than usual buffer. – tgdavies Jun 13 '22 at 07:49
  • 1
    The whole concept has a code smell to me. Keeping an IO object in a field is rarely a good idea, an even worse one to open it in one method and closing it in another. Maybe you want to describe your use case to enable people to give you better impulses. – daniu Jun 13 '22 at 08:17
  • @daniu This is a part of my kafka listener function. I'm trying to consume a large size of data, so I choose to save the writer in a hashmap. I'm not sure whether it's a better idea if I repeat closing the writer and creating new one again. – John Smith Jun 13 '22 at 08:27
  • Once you've closed the Writer, you can't use it again. So your `write` method will use the Writer just once. It looks like you intended to reuse the same Writer when calling `write` many times. In that case, you want to call `flush()` instead of `close()`. – k314159 Jun 13 '22 at 08:42

2 Answers2

0

You can handle it with a try - catch - finally sentence. Something like:

try {
    // Do things
} catch (Exception e) {
    e.printStackTrace();
} finally {
    if (myBufferedWriter != null) {
        try {
            myBufferedWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Inazense
  • 1,517
  • 3
  • 18
  • 28
0

Your best bet is The try-with-resources Statement.

The try-with-resources statement ensures that each resource is closed at the end of the statement. [...] the try-with-resources statement contains [...] declarations that are separated by a semicolon[...]. When the block of code that directly follows it terminates, either normally or because of an exception, the close methods of the [...] objects are automatically called in this order. Note that the close methods of resources are called in the opposite order of their creation.

public static void writeToFileZipFileContents(String zipFileName,
                                           String outputFileName)
                                           throws java.io.IOException {

    java.nio.charset.Charset charset =
         java.nio.charset.StandardCharsets.US_ASCII;
    java.nio.file.Path outputFilePath =
         java.nio.file.Paths.get(outputFileName);

    // Open zip file and create output file with 
    // try-with-resources statement

    try (
        java.util.zip.ZipFile zf =
             new java.util.zip.ZipFile(zipFileName);
        java.io.BufferedWriter writer = 
            java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
    ) {
        // Enumerate each entry
        for (java.util.Enumeration entries =
                                zf.entries(); entries.hasMoreElements();) {
            // Get the entry name and write it to the output file
            String newLine = System.getProperty("line.separator");
            String zipEntryName =
                 ((java.util.zip.ZipEntry)entries.nextElement()).getName() +
                 newLine;
            writer.write(zipEntryName, 0, zipEntryName.length());
        }
    }
}
peterulb
  • 2,869
  • 13
  • 20
  • pls refer to my edited question – John Smith Jun 13 '22 at 08:07
  • @JohnSmith You could put it in write and propagate the exception like in the code example. You might need to cleanup the map though, since it's Writer is then closed. In your comment you mentioned it's closed there anyway, so you'd need to handle the map no matter what – peterulb Jun 13 '22 at 08:17