io

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:

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.

write to file java - filewriter

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:

  1. In main, we’ve used a ByteArrayInputStream to obtain an input stream from a String.
  2. We’ve used Channels.newChannel to obtain an ReadableByteChannel from the InputStream.
  3. You can also see how to open multiple resources in one try clause.
  4. 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.

Download
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

Nikos Maravitsas

Nikos has graduated from the Department of Informatics and Telecommunications of The National and Kapodistrian University of Athens. During his studies he discovered his interests about software development and he has successfully completed numerous assignments in a variety of fields. Currently, his main interests are system’s security, parallel systems, artificial intelligence, operating systems, system programming, telecommunications, web applications, human – machine interaction and mobile development.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button