SwadhyAI Notes

All Java notes

Java FileOutputStream

›Short versionOpen if you only have a minute.
  • FileOutputStream writes bytes. Opening it without append truncates an existing file immediately.
  • Pass true to append. The file is created if it is missing. Parent folders are not.
  • Encode a String with a named charset, such as UTF-8, before you write the bytes.
  • After a partial read, write(buffer, 0, count) so the stale tail stays out of the file.
  • This class does not keep a character buffer. A BufferedWriter in front of it does, and that buffer can hide a failure until flush or close.

A is the byte stream that sends data to a file. What you pass to write is what lands in the file, in order, from the position the constructor chose.

Open, then the old bytes are gone

The usual constructor . The moment new FileOutputStream("output.txt") returns, an existing file has length 0. Plan on that. A crash before the first write still leaves an empty file.

Text has to become bytes through a . Name UTF-8 at getBytes. The no-argument getBytes() uses the JVM default, which is a quiet way to produce a file other machines read wrong.

WriteBytes.java
String message = "Hello from Java I/O";
try (FileOutputStream output = new FileOutputStream("output.txt")) {
    output.write(message.getBytes(StandardCharsets.UTF_8));
}

keeps the old bytes. The second argument is true.

AppendLog.java
try (FileOutputStream output = new FileOutputStream("app.log", true)) {
    output.write("Application started\n".getBytes(StandardCharsets.UTF_8));
}

Write only the bytes you read

Copying from a FileInputStream reuses one array. read tells you how many slots are new. write(chunk, 0, count) sends that prefix. The three-argument write is the one that matches a partial read.

CopyFile.java
byte[] chunk = new byte[8192];
try (FileInputStream input = new FileInputStream("source.bin");
     FileOutputStream output = new FileOutputStream("copy.bin")) {
    int count;
    while ((count = input.read(chunk)) != -1) {
        output.write(chunk, 0, count);
    }
}

Both streams are declared in the try. They close in reverse order: the output stream first, then the input stream. Neither one is a character buffer, so there is nothing sitting in Java memory after write returns. The operating system may still be holding the pages, and on FileOutputStream does not force them to disk.

Who closes

closes what the block opened. For the copy above, that is both file streams. For text, own the outer writer and let its close walk down to this stream.

WriteText.java
try (BufferedWriter writer = new BufferedWriter(
        new OutputStreamWriter(new FileOutputStream("notes.txt"), StandardCharsets.UTF_8))) {
    writer.write("Hello");
    writer.newLine();
}

Closing the BufferedWriter flushes, then closes the OutputStreamWriter, which closes the FileOutputStream. One owner, one close. A helper that was handed an open stream should write and return. Closing a wrapper around a borrowed stream would close the caller's file, and it would flush at a moment the caller did not choose.

new FileOutputStream("report.txt") returns, and the program is killed before write. The file used to hold a finished report. What is in it now?

Nothing. The constructor truncated it to length 0 before any write. Append mode, the true argument, would have left the old report in place. The kill happened too early to add bytes, and too late to save the previous ones.