3

I'm reading a large file using the nio Files.lines method, and writing it to another file.

BufferedWriter writer = Files.newBufferedWriter(Path.of(outFile);

         Files.lines(Path.of(inputFile))
                .forEach(line -> {
                    try {
                        writer.write(line);
                        writer.newLine();
                    } catch (IOException e) {
                        throw new UncheckedIOException(e);
                    }
                });
        writer.flush();
        writer.close();
    

I want to close the writer and the stream (Files.lines) in a finally block. I'm aware I'll have to surround this snippet in a try-catch-finally block, but how do I close the stream without assigning it to a variable?

Didier L
  • 18,905
  • 10
  • 61
  • 103
CtrlAltElite
  • 487
  • 8
  • 32
  • 1
    You can't close without assigning it to a variable. How can you write to it, without assigning into a variable? – Ravindra Ranwala Mar 03 '21 at 07:38
  • 4
    Use [`Files.copy(Path.of(inputFile), Path.of(outFile))`](https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/nio/file/Files.html#copy(java.nio.file.Path,java.nio.file.Path,java.nio.file.CopyOption...)). There’s no sense in decoding the file’s bytes to characters, identifying line breaks, breaking the text into line strings, joining the lines again in the writer’s buffer, and encoding it to bytes again when you can copy the bytes as-is in the first place. Especially for “a large file”. – Holger Mar 03 '21 at 08:15
  • 1
    @GauthamM because the specification of [`Files.lines(…)`](https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/nio/file/Files.html#lines(java.nio.file.Path)) says so: “*This method must be used within a try-with-resources statement or similar control structure to ensure that the stream's open file is closed promptly after the stream's operations have completed.*” – Holger Mar 03 '21 at 08:21
  • 1
    Does this answer your question? [Close Java 8 Stream](https://stackoverflow.com/questions/38698182/close-java-8-stream) – Gautham M Mar 03 '21 at 08:22

1 Answers1

4

Instead of doing lots of manual work, just use the following snippet (as you've been advised already in the comments):

Files.copy(Path.of(inputFile), Path.of(outFile)));

If you still want to do that manually for some reason, use try-with-resources. You will still assign the BufferedWriter to a variable, but there'll be no need to close it explicitly. Java will do that by itself:

try(BufferedWriter writer = Files.newBufferedWriter(Path.of(outFile));
    Stream<String> lines = Files.lines(Path.of(inputFile))) {
    // ... do something with your lines & writer here
}
ETO
  • 6,970
  • 1
  • 20
  • 37