When working on an enterprise application, sometimes it is necessary to write the text or binary data into files in Java e.g. writing user-generated reports into the filesystem.
Though there are multiple ways of writing the files in Java, let’s quickly go through a few of them for quick reference when it is needed.
String content = "some text";
// Java 11
Files.writeString(Path.of("demo.txt"), content);
// Using Files class
Files.write(Path.of("demo.txt"), content.getBytes());
// Using BufferedWriter
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath.toFile()))) {
writer.write(content);
}
// Using FileWriter
try(FileWriter fileWriter = new FileWriter(Path.of("demo.txt").toFile())){
fileWriter.write(content);
}
// Write to binary file
try(FileOutputStream outputStream = new FileOutputStream(Path.of("demo.txt").toFile())){
byte[] strToBytes = content.getBytes();
outputStream.write(strToBytes);
}
1. Using Files.writeString() – Java 11
Starting with Java 11, the Files.writeString()
method offers a convenient way to write text to a file. It accepts a Path
parameter and a string, simplifying the process of writing text content in a single-line statement.
- As the name suggests, writeString() method is used to write the character/text data into files.
- All characters are written as they are, including the line separators. No extra characters are added.
- By default, UTF-8 character encoding is used.
- It throws IOException if an I/O error occurs when writing to or creating the file, or if the text cannot be encoded using the specified charset.
Path filePath = Path.of("demo.txt");
String content = "hello world !!";
Files.writeString(filePath, content);
2. Write to File using Files.write()
Files class is another method write() since Java 7 and it works similarly to writeString(). It takes a Path
and a byte array as parameters.
The write() method is suitable for writing binary data as well as it can also be used for writing text data, as shown in the following example.
Path filePath = Path.of("demo.txt");
String content = "hello world !!";
//Write bytes
Files.write(filePath, content.getBytes());
//Write lines
List<String> lines = Arrays.asList("a", "b", "c");
Files.write(filePath, lines, StandardCharsets.UTF_8);
3. Fast Writing with FileChannel and ByteBuffer
FileChannel
can be used for reading, writing, mapping, and manipulating a file. If we are writing large files, FileChannel
can be faster than standard IO.
File channels are safe for use by multiple concurrent threads.
Path fileName = Path.of("demo.txt");
String content = "hello world !!";
try (
RandomAccessFile stream = new RandomAccessFile(filePath.toFile(),"rw");
FileChannel channel = stream.getChannel();) {
byte[] strBytes = content.getBytes();
ByteBuffer buffer = ByteBuffer.allocate(strBytes.length);
buffer.put(strBytes);
buffer.flip();
channel.write(buffer);
}
4. Write to Text File with BufferedWriter
BufferedWriter
the most traditional and simplest way to write the content to a file. It writes text to a character-output stream, buffering characters so as to provide for the efficient writing of single characters, arrays, and strings.
Unless prompt output is required, it is advisable to wrap a BufferedWriter
around any Writer
whose write()
operations may be costly, such as FileWriter
and OutputStreamWriter
, especially when writing large amounts of data.
As it buffers before writing, it results in fewer IO operations, so it improves the performance.
Path filePath = Path.of("demo.txt");
String content = "hello world !!";
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath.toFile()))) {
writer.write(content);
}
5. Write to File with FileWriter or PrintWriter
FileWriter
the cleanest way to write files and the syntax is self-explanatory and easy to read and understand. FileWriter writes directly into the file (less performance) and should be used only when the number of writes is less.
Because the FileWriter does not offer buffering, it can lead to performance issues when writing large amounts of data.
Path filePath = Path.of("demo.txt");
String content = "hello world !!";
try(FileWriter fileWriter = new FileWriter(filePath.toFile())){
fileWriter.write(content);
}
Use PrintWriter
to write formatted text to a file. This class implements all of the print methods found in PrintStream
, so you can use all formats that you use with System.out.println()
statements.
Path filePath = Path.of("demo.txt");
String content = "hello world !!";
try(FileWriter fileWriter = new FileWriter(filePath.toFile());
PrintWriter printWriter = new PrintWriter(fileWriter);){
printWriter.print(content);
printWriter.printf("Blog name is %s", "howtodoinjava.com");
}
6. Write to Binary File with FileOutputStream
Use FileOutputStream
to write binary data to a file. FileOutputStream
is meant for writing streams of raw bytes such as image data. For writing streams of characters, consider using FileWriter
.
Path filePath = Path.of("demo.txt");
String content = "hello world !!";
try(FileOutputStream outputStream = new FileOutputStream(filePath.toFile())){
byte[] strToBytes = content.getBytes();
outputStream.write(strToBytes);
}
7. Write to File with DataOutputStream
DataOutputStream
lets an application write primitive Java data types to an output stream in a portable way. An application can then use a data input stream to read the data back in.
Path filePath = Path.of("demo.txt");
String content = "hello world !!";
try (
FileOutputStream outputStream
= new FileOutputStream(filePath.toFile());
DataOutputStream dataOutStream
= new DataOutputStream(new BufferedOutputStream(outputStream));) {
dataOutStream.writeUTF(content);
dataOutStream.writeInt(10);
dataOutStream.writeLong(100L);
}
7. Clean Code vs. Performance
When considering performance, there are several factors to take into account:
- Convenience:
Files.writeString()
is the most convenient for writing text data, whileFiles.write()
is suitable for binary data. These methods provide an easy-to-use API. - Buffering:
BufferedWriter
andFiles.write()
provide buffering, which can significantly improve write performance, especially when dealing with large amounts of data. - Binary vs. Text Data: If you need to write binary data,
FileOutputStream
is the best choice. For text data, the decision depends on the level of convenience and the need for buffering as discussed above.
For smaller files, we may prefer readability weighing over other factors because the performance gains will be negligible. Ther FileWriter
and Files.writeString()
should be preferred choices in case of smaller files.
For a large amount of data, we will require a better raw performance. In this case, buffered methods like BufferedWriter
and Files.write()
can offer improved efficiency.
Ultimately, the choice of method should depend on the specific requirements, such as data volume, simplicity, and readability.
8. Summary
- If we try to write to a file that doesn’t exist, the file will be created first and no exception will be thrown (except using
Path
method). - Always close the output stream after writing the file content to release all resources. It will also help in not corrupting the file.
- Use
PrintWriter
is used to write formatted text. - Use
FileOutputStream
to write binary data. - Use
DataOutputStream
to write primitive data types. - Use
FileChannel
to write larger files. It is the preferred way of writing files in Java 8 as well.
Happy Learning !!
Comments