Java write to File Example
In this post, we feature a comprehensive example of how to write to File in Java using FileWriter, FileOutputStream, and NIO. We are going to investigate several methods to write a File in Java.
We will list some of the older, before Java 7 and NIO, methods to write to a text or a binary file as well as some of the modern ones. You are also going to notice that we use some methods to write to larger files and other methods to write to smaller files. Efficiently writing large amounts of data to files usually requires some buffering, which is not necessary for smaller files.
Ok, let’s start with the older, before NIO methods.
1. Using classic IO libraries
1.1 Write files using FileWriter and FileOutputStream in Java
Let’s see the code on how to write on files using FileWriter and then we will analyze it:
WriteToFileExample.java:
package com.javacodegeeks.core.writeToFile; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.ArrayList; import java.util.List; public class WriteToFileExample { private static final String FILEPATH = "C:\\Users\\nikos\\Desktop\\TestFiles\\testFile.txt"; public static void main(String[] args) throws IOException { String str1 = "abc"; String str2 = "asdasfasfasfa"; List<String> list = new ArrayList<String>(); list.add(str1); list.add(str2); //useBufferedFileOutPutStream(list, FILEPATH); useFileOutPutStream(str1,FILEPATH); } /** * Write a small string to a File - Use a FileWriter */ public static void useFileWriter(String content, String filePath) { Writer writer = null; try { writer = new FileWriter(filePath); writer.write(content); } catch (IOException e) { System.err.println("Error writing the file : "); e.printStackTrace(); } finally { if (writer != null) { try { writer.close(); } catch (IOException e) { System.err.println("Error closing the file : "); e.printStackTrace(); } } } } /** * Write a big list of Strings to a file - Use a BufferedWriter */ public static void useByfferedFileWriter(List<String> content, String filePath) { File file = new File(filePath); Writer fileWriter = null; BufferedWriter bufferedWriter = null; try { fileWriter = new FileWriter(file); bufferedWriter = new BufferedWriter(fileWriter); // Write the lines one by one for (String line : content) { line += System.getProperty("line.separator"); bufferedWriter.write(line); // alternatively add bufferedWriter.newLine() to change line } } catch (IOException e) { System.err.println("Error writing the file : "); e.printStackTrace(); } finally { if (bufferedWriter != null && fileWriter != null) { try { bufferedWriter.close(); fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * Write raw data to a small file - use FileOutPutStream */ public static void useFileOutPutStream(String content, String filePath) { OutputStream outputStream = null; try { outputStream = new FileOutputStream(new File(filePath)); outputStream.write(content.getBytes(), 0, content.length()); } catch (FileNotFoundException e) { System.err.println("Error Opening the file : "); e.printStackTrace(); } catch (IOException e) { System.err.println("Error writing the file : "); e.printStackTrace(); } finally { if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * Write character data to a big file - use BufferedWriter */ public static void useBufferedFileOutPutStream(List<String> content, String filePath) { Writer writer = null; try { // Using OutputStreamWriter you don't have to convert the String to byte[] writer = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(filePath), "utf-8")); for (String line : content) { line += System.getProperty("line.separator"); writer.write(line); } } catch (IOException e) { } finally { if (writer != null) { try { writer.close(); } catch (Exception e) { } } } } /** * Write raw data to a big file - use BufferedOutputStream */ public static void useBufferedOutPutStream(List<String> content,String filePath) { BufferedOutputStream bout = null; try { bout = new BufferedOutputStream( new FileOutputStream(filePath) ); for (String line : content) { line += System.getProperty("line.separator"); bout.write(line.getBytes()); } } catch (IOException e) { } finally { if (bout != null) { try { bout.close(); } catch (Exception e) { } } } } }
In the above example we basically use two different methods:
- FileWriter to write to character/text files in Java.
FileOutputStream
to write raw data.
In order to buffer the writes of the above classes, we use a BufferedWriter
for character streams and BufferedOutputStream
for raw data streams. With BufferedWriter
, we simply use an internal buffer to pack the data we want to write and reduce real IO operations, which essentially saves time. So as you can imagine, this is very useful when creating a write-intensive application that writes large amounts of data to files.
BufferedWriter
is generally created with the default buffer size, which is sufficient for most applications. If you want you can specify the size of the internal buffer using this constructor instead : BufferedWriter(Writer out, int sz)
where sz
is the size of the buffer in bytes.
It’s also worth noting that both of the above classes use the default character set of the underlying systems. If, for some reason, you want to specify the character yourself you can use OutputStreamWriter
to wrap FileOutputStream
. Furthermore when writing characters to a file without buffering, on every write
invocation the system will perform a conversion from characters to bytes. Buffering will also reduce the amount of conversions performed.
1.2 Using RandomAccessFile
RandomAccessFile
was introduced to support random accessed to files. As the javadoc says “a random access file behaves like a large array of bytes stored in the file system”. It is a very convenient class to write and also read files in arbitrary positions.
Let’s see how:
WriteToFileNIO.java:
public static void writeWithRandmoAccessFile( String content, String filePath) { try (RandomAccessFile randomAccessFile = new RandomAccessFile(new File(filePath), "rw")) { // move the cursor to the end of the file // you can move the cursor to any position inside the file to write at random positions randomAccessFile.seek(randomAccessFile.length()); randomAccessFile.write(content.getBytes()); // alternatively you can use randomAccessFile.writeChars(content) // or randomAccessFile.writeUTF(content); } catch (IOException e) { e.printStackTrace(); } }
As you can see we open a RandomAccessFile
in read-write mode. Then, we simply move the cursor to the end of the file to append the new content (using seek
method) and we simply write some bytes to it with its write
method. Note that RandomAccessFile
was introduced in JDK1.0.
That’s it. Now let’s take a see how can write to files in Java using modern NIO classes.
2. Write files using NIO
NIO introduced several classes that made File manipulation easier and highly efficient. We are also going to introduce here the try-with resources syntax.
2.1 Using java.nio.file.Files class
Let’s see the code:
WriteToFileNIO.java:
package com.javacodegeeks.core.writeToFile; import java.io.BufferedOutputStream; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; public class WriteToFileNIO { private static final String FILEPATH = "C:\\Users\\nikos\\Desktop\\TestFiles\\testFile.txt"; public static void main(String[] args) throws IOException { String str1 = "abc"; String str2 = "aipcipasincinainsovusdvweviasbdoviuabsudviuadv"; List<String> list = new ArrayList<String>(); list.add(str1); list.add(str2); bufferedWrite(list, FILEPATH); } /** * Write a small string to a File - Use a FileWriter */ public static void simpleWrite(String content, String filePath) { Path fileP = Paths.get(filePath); try { Files.write(fileP, content.getBytes("utf-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * Write a big list of Strings to a file - Use a BufferedWriter */ public static void bufferedWrite(List<String> content, String filePath) { Path fileP = Paths.get(filePath); Charset charset = Charset.forName("utf-8"); try (BufferedWriter writer = Files.newBufferedWriter(fileP, charset)) { for (String line : content) { writer.write(line, 0, line.length()); writer.newLine(); } } catch (IOException e) { e.printStackTrace(); } } /** * Write raw data to file - use OutputStream */ public static void writeWithOutputStream(String content, String filePath) { Path fileP = Paths.get(filePath); try (OutputStream outputStream = Files.newOutputStream(fileP)) { outputStream.write(content.getBytes()); } catch (IOException e) { e.printStackTrace(); } } /** * Write raw data to file using BufferedOutputStream */ public static void writeWithBufferedOutputStream(List<String> content, String filePath) { Path fileP = Paths.get(filePath); try (BufferedOutputStream outputStream = new BufferedOutputStream(Files.newOutputStream(fileP))) { for (String line : content) { outputStream.write(line.getBytes()); } } catch (IOException e) { e.printStackTrace(); } } /** * Write a string list to a File */ public static void simpleWriteListOfString(List<String> content, String filePath) { Path fileP = Paths.get(filePath); Charset charset = Charset.forName("utf-8"); try { Files.write(fileP, content,charset); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
As you can see things are much simpler because of the new NIO Files
class and the new try-with resource syntax. In try-with resource syntax, when you open a resource in the try()
clause, the resource will be automatically closed when the flow of the program exits the try
region. You don’t have to create the finally
block to release the resources as we did previously.
2.2 Using FileChannel
Now let’s see how you can use FileChannel
, which is a very interesting class of the NIO package. It basically connects a channel of bytes to a file and enables both reading and writing from/to files. You can view it as an alternative to FileOuputStream
. A major difference is that a FileChannel
connects an allocated byte buffer to the file and it holds the current position of the cursor in the file.
WriteToFileNIO.java:
public static void writeWithFileChannel(String content, String filePath) { try (RandomAccessFile randomAccessFile = new RandomAccessFile(new File(filePath), "rw")) { // move the cursor to the end of the file randomAccessFile.seek(randomAccessFile.length()); // obtain the a file channel from the RandomAccessFile try (FileChannel fileChannel = randomAccessFile.getChannel()) { ByteBuffer buf = ByteBuffer.allocate(512); buf.clear(); buf.put(content.getBytes()); buf.flip(); while (buf.hasRemaining()) { fileChannel.write(buf); } } catch (IOException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } }
As you can see we first create a RandomAccessFile
and obtain a FileChannel
from it. Then, we allocate a ByteBuffer
of 512 bytes. Finally we write the contents of the byte buffer to the file. For performance reasons, it’s not guaranteed that that the buffer will be written in its entirety to the file in a single write
operation. That’s why we’ve used the while loop, so as log as the buffer has remaining bytes in it, we simply append them to the file.
2.3 Using FileChannel and memory mapped file
In the following methods we are also going to use a MappedByteBuffer
. This is a direct byte buffer that maps a memory region to a file region.
Let’s see how you do this :
WriteToFileNIO.java:
public static void writeWithMemMappedBuffer(String content, String filePath) { try (RandomAccessFile randomAccessFile = new RandomAccessFile(new File(filePath), "rw")) { // move the cursor to the end of the file randomAccessFile.seek(randomAccessFile.length()); // obtain the a file channel from the RandomAccessFile try (FileChannel fileChannel = randomAccessFile.getChannel()) { // Map a content.getBytes().length byte region of the file to this memory buffer MappedByteBuffer memoryMappedbuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, fileChannel.position(),content.getBytes().length); memoryMappedbuffer.put(content.getBytes()); } catch (IOException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } }
You can use this for performance sensitive applications. As you can see, there is no need to explicitly write the buffer to the file, that is something that the underlying systems does when it deems its necessary. You only have to manipulate the buffer, and the changes will be reflected to the file. Of course, reads are very efficient using this technique as well.
2.4 FileChannel and Direct Memory Access
There is an excellent article form IBM that describes Efficient data transfer through zero copy. In this case we are going to use transferTo()/transferFrom()
method of FileChannel
class. It’s basic characteristics is that the it relies on the underlying system to access its DMA (Direct Memory Access) infrastructure. It might not work in all operating systems, but most modern ones offer such capabilities. What happens is that data are transferred directly from/to disc to the bus, avoiding CPU copies.
It’s recommended to use that technique to transfer data from one source channel to another destination channel, e.g from a file to another file, from a file to a socket, from a database to a file and so on. But we are going to show you how to transfer data from a String
to a FileChannel
. We are going to consider the String
as an InputStream
from a data source (think hundreds of MB or GB long strings).
WriteToFileNIO.java:
package com.javacodegeeks.core.writeToFile; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; import java.nio.charset.Charset; public class WriteToFileNIO { private static final String FILEPATH = "C:\\Users\\nikos\\Desktop\\TestFiles\\testFile.txt"; public static void main(String[] args) throws IOException { String str2 = "aipcipasincinainsovusdvweviasbdoviuabsudviuadv"; long numBytes = str2.getBytes().length; // obtain an inputstream from the string InputStream inputStream = new ByteArrayInputStream(str2.getBytes(Charset.forName("UTF-8"))); writeWithFileChannerDMA(inputStream,FILEPATH,numBytes); } /** * Write to a file using a FileChanel and DMA */ public static void writeWithFileChannerDMA(InputStream inputStream, String outputFile, long count) { try (RandomAccessFile randomAccessFile = new RandomAccessFile(new File( outputFile), "rw")) { // move the cursor to the end of the file randomAccessFile.seek(randomAccessFile.length()); // obtain the a file channel from the RandomAccessFile try ( FileChannel fileChannel = randomAccessFile.getChannel(); ReadableByteChannel inputChannel = Channels.newChannel(inputStream); ) { fileChannel.transferFrom(inputChannel, 0, count); } catch (IOException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } } }
So, in the above example you’ve seen 4 major things:
- In
main
, we’ve used aByteArrayInputStream
to obtain an input stream from aString
. - We’ve used
Channels.newChannel
to obtain anReadableByteChannel
from theInputStream
. - You can also see how to open multiple resources in one
try
clause. - We’ve used
transferFrom
to transfer data from one channel to the other. Hopping that the underlying system will offer DMA infrastructure, data can be transferred directly to the file system without any copying in between.
That was it! A lot of solutions there to suit every need. That was a comprehensive example of how to write to File in Java using FileWriter, FileOutputStream, and NIO.
I hope you find this guide useful.
3. Download the Source Code
This was an example on how to write files in Java using FileWriter.
You can download the source code of the Java write to File example here: Java write to File Example
Last updated on Feb. 17th, 2020