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.
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.
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.
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.
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.