Lewis D.
—You need to write data to a file in Java. How can you do this?
If you read the Sentry answer to How to Read to a File in Java, you’ll know that there are numerous solutions to reading from files in Java. Similarly, there are many ways you can write data to a file, and certain implementations may be more suitable to your needs than others, depending on the amount and type of data you are writing to a file.
Let’s take a look at some of Java’s built-in file-writing solutions, and consider which situations they are useful in.
Files
class to write textual data to a file.BufferedWriter
will help eliminate the overhead of slow write operations.FileOutputStream
optionally wrapped in a BufferedOutputStream
.Files
ClassTo write a small simple file, the Files
class has a very intuitive approach using the write()
method.
In this method, you pass the data encoded as bytes and a path to the file, and the Files
class handles the file-writing process as shown below:
public void writeToFile(Path path, String content) { try { Files.write(path, content.getBytes()); } catch (IOException e) { // exception handling ... } }
Since Java 11, a writeString()
method is available to handle passing in a String
directly, bypassing the need to first encode the String
to bytes.
FileWriter
ClassThe FileWriter
class has been around since Java 1.1, and it’s a convenient class for writing character-oriented files. The syntax for FileWriter
is concise and intuitive.
An advantage of using the FileWriter
class is that it has a boolean
parameter append
, which can be supplied when invoking a new class. If append
is true, then the data that is written will be appended to the end of the file, instead of overwriting the file entirely.
Here’s a code example to write and append to a file:
public void writeToFile(String path, String content, boolean append) { try (FileWriter fileWriter = new FileWriter(path, append)) { fileWriter.write(content); } catch (IOException e) { // exception handling ... } }
In this example, the try-with-resources construct is used, which negates the need to explicitly close the writer when we are finished with it. Note that if you did not use the try-with-resources, you will need to remember to close the writer yourself once you’re finished writing.
BufferedWriter
ClassThe BufferedWriter
class, as its name suggests, supports buffering. When the write()
method is called, the data is written to the BufferedWriter
’s internal buffer, and persisted to file only when this internal buffer is completely filled. This buffering process reduces the number of expensive write operations the code needs to make, so the BufferedWriter
is most suited to writing large files efficiently.
Here’s an example using the BufferedWriter
class:
public void writeToFile(String path, String content, boolean append) { try(BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(path, append))){ bufferedWriter.write(content); } catch (IOException e) { // exception handling ... } }
In this example, the BufferedWriter
is created with the try-with-resources construct and when the try-with-resources automatically closes the BufferedWriter
, the FileWriter
which the BufferedWriter
writes to will also be closed. So in this case, the FileWriter
will be closed at the same time the BufferedWriter
instance is closed.
FileOutputStream
and BufferedOutputStream
ClassesIn the three approaches we’ve explored so far, we have focussed on writing character-oriented data to file. However, the FileOutputStream
class can be used to write streams of byte-oriented data, such images or Unicode data, and other data that can’t be represented as text. Of course, you can write textual data to file using a FileOutputStream
by simply encoding the String
text to bytes.
public void writeToFile(String path, byte[] content) { try (FileOutputStream outputStream = new FileOutputStream(path)) { outputStream.write(content); } catch (IOException e) { // exception handling ... } }
Similarly, the BufferedOutputStream
class adds buffering to the underlying OutputStream
for increased efficiency.
In our FileOutputStream
example above, we could wrap the underlying OutputStream
in a BufferedOutputStream
to buffer all bytes until they are written.
public void writeToFile(String path, byte[] content) { try(BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(path))) { bufferedOutputStream.write(content); } catch (IOException e) { // exception handling ... } }
There are no set criteria for when a BufferedOutputStream
should be used, so you should consider buffer size, disk speed, and network speed (if applicable) and how these factors influence potential performance gains or losses before settling on this option for writing to a file.
Tasty treats for web developers brought to you by Sentry. Get tips and tricks from Wes Bos and Scott Tolinski.
SEE EPISODESConsidered “not bad” by 4 million developers and more than 100,000 organizations worldwide, Sentry provides code-level observability to many of the world’s best-known companies like Disney, Peloton, Cloudflare, Eventbrite, Slack, Supercell, and Rockstar Games. Each month we process billions of exceptions from the most popular products on the internet.
Here’s a quick look at how Sentry handles your personal information (PII).
×We collect PII about people browsing our website, users of the Sentry service, prospective customers, and people who otherwise interact with us.
What if my PII is included in data sent to Sentry by a Sentry customer (e.g., someone using Sentry to monitor their app)? In this case you have to contact the Sentry customer (e.g., the maker of the app). We do not control the data that is sent to us through the Sentry service for the purposes of application monitoring.
Am I included?We may disclose your PII to the following type of recipients:
You may have the following rights related to your PII:
If you have any questions or concerns about your privacy at Sentry, please email us at compliance@sentry.io.
If you are a California resident, see our Supplemental notice.