{"id":3070,"date":"2024-03-28T16:00:00","date_gmt":"2024-03-28T16:00:00","guid":{"rendered":"https:\/\/msgprogramator.sk\/?p=3070"},"modified":"2025-07-07T10:57:32","modified_gmt":"2025-07-07T10:57:32","slug":"write-java-files","status":"publish","type":"post","link":"https:\/\/msgprogramator.sk\/en\/write-java-files\/","title":{"rendered":"Java File Handling Part 2: How to write files in Java quickly and efficiently"},"content":{"rendered":"<p>If you read our previous article on how to <strong><a href=\"https:\/\/msgprogramator.sk\/en\/read-java-files\/\">Read Java Files<\/a><\/strong> you already know that there are many different ways to read files in Java. Depending on the type of file and its size, you need to choose the right approach to the solution, because it may take too long to load the files.<\/p>\n<p>Similarly, there are many ways you can write data to a Java file. Certain implementations may be better suited for a given solution than others, depending on the type and amount of data you write to the file. When writing to a file, we need to know in advance whether we are going to write our data to a text file or a binary file. In the case of a text file, we will focus on the use of classes such as: <strong><em>Files, Writer, OutputStreamWriter, FileWriter, PrintWriter, BufferedWriter<\/em><\/strong>. For binary files, we will use classes such as: <strong><em>OutputStream, FileOutputStream, BufferedOutputStream<\/em><\/strong>, <strong><em>ByteArrayOutputStream, DataOutputStream<\/em><\/strong>. There are also external third-party libraries available for working with files, which we will not deal with today.<\/p>\n<p>Each of the file-handling classes mentioned above has its use for specific cases. In general, however, we use <strong><em>OutputStream<\/em><\/strong> for binary data and <strong><em>Writer<\/em><\/strong> for text. <\/p>\n<p>Most of the pre-defined classes for reading and writing files in Java are located in the <strong>java.io<\/strong> and <strong>java.nio.file<\/strong> packages. With the introduction of the new Java NIO.2 (New I\/O) File API, the situation became even more complicated, and how to work with files efficiently is often a common question on programming forums, even among experienced developers.<\/p>\n<p>Writing data in Java can also get complicated, so in our article we will focus on two basic data writing scenarios that will cover 90 percent of use cases, which are:<\/p>\n<ul>\n<li>The simplest way to write once to both binary and text files.<\/li>\n<li>Continuous writing to a file in parts.<\/li>\n<\/ul>\n<p>Java 7 brought the long-awaited <em>NIO.2 File API, <\/em>which, besides a lot of functionality, also brought a helper class <strong>java.nio.file.Files<\/strong>, which can be used to write a byte array, a string or a list of strings to a text\/binary file with a single command.<\/p>\n<h2>Writing a byte array to a binary file<\/h2>\n<p>You can write a byte array to a file as follows:<\/p>\n<pre><code class=\"language-java\" data-line=\"\">import java.nio.file.Files;\nimport java.nio.file.Path;\n\nString fileName = &quot;fileName.dat&quot;;\nbyte[] data = {72, 101, 108, 108, 111};\nFiles.write(Path.of(fileName), data);\n<\/code><\/pre>\n<p>The <em>Path<\/em> class (available from Java 11 onwards) represents an abstraction of a file and contains the path to the file in the file system.<\/p>\n<h2>Writing a variable of the String type to a text file<\/h2>\n<p>Writing a variable of type String to a file is very easy since Java 11:<\/p>\n<pre><code class=\"language-java\" data-line=\"\">import java.nio.file.Files;\nimport java.nio.file.Path;\n\nString fileName = &quot;fileName.txt&quot;;\nString text = &quot;Hello&quot;;\nFiles.writeString(Path.of(fileName), text);\n<\/code><\/pre>\n<h2>Writing a list of String variables to a text file<\/h2>\n<p>Often we don&#8217;t write one line to a text file, but several lines at a time. With the following command you can write a list or more precisely <em>Iterable&lt;? extends CharSequence &gt;<\/em>) to a text file.<\/p>\n<pre><code class=\"language-java\" data-line=\"\">import java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\nString fileName = &quot;fileName.txt&quot;;\nList&lt;String&gt; lines = new ArrayList&lt;&gt;(Arrays.asList(&quot;msg&quot;, &quot;life&quot;));\nFiles.write(Path.of(fileName), lines);\n<\/code><\/pre>\n<h2>Writing to a text file using a String stream<\/h2>\n<p>There is no method that writes directly from a String stream to a file, but there is a little trick that can be used to achieve this:<\/p>\n<pre><code class=\"language-java\" data-line=\"\">import java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.stream.Stream;\n\nString fileName = &quot;fileName.txt&quot;;\nStream&lt;String&gt; lines = new ArrayList&lt;&gt;(Arrays.asList(&quot;msg&quot;, &quot;life&quot;)).stream();\nFiles.write(Path.of(fileName), (Iterable&lt;String&gt;) lines::iterator);<\/code><\/pre>\n<p>We use the <em>Files.write()<\/em> method as in the previous example, but it only accepts the <em>Iterable&lt;String&gt;<\/em> argument. The stream itself is not iterable in Java 8 because it can only be called once (repeated calls would result in an <em>IllegalStateException<\/em>). Thus, it cannot be used as a parameter. There is, however, a functional <em>Iterable<\/em> interface whose only method returns an <em>Iterator<\/em>. Therefore, we can pass a reference to the <em>lines.iterator()<\/em> method, which will also return an iterator as an <em>Iterable<\/em>.<\/p>\n<p>In this section, we have been introduced to the helper methods of the <em>java.nio.file.Files<\/em> class. These methods are suitable for all use cases where the data we want to write to a file is completely stored in memory and the data range is only a few kilobytes.<\/p>\n<p>In other cases, and especially when the file is written repeatedly in parts, it is better to use one of the predefined <em>OutputStream<\/em> classes. In the next section we will explain how to do this.<\/p>\n<h2>Writing quickly to binary files using BufferedOutputStream<\/h2>\n<p>The main class for writing binary data to a file is <strong><em>FileOutputStream<\/em><\/strong>, which allows you to write a byte to a file, or an array of bytes. Writing individual bytes is a very expensive operation, so we recommend using a buffer and writing the file in blocks (called buffering), which is significantly faster. On most systems, the optimal buffer size is 8 KB, so Java uses this value as the default. For buffered notation we use the class <strong><em>BufferedOutputStream<\/em><\/strong> as follows.<\/p>\n<pre><code class=\"language-java\" data-line=\"\">import java.io.BufferedOutputStream;\nimport java.io.FileOutputStream;\n\nString fileName = &quot;fileName.dat&quot;;\nbyte[] bytes;\ntry (FileOutputStream out = new FileOutputStream(fileName);\n     BufferedOutputStream bout = new BufferedOutputStream(out)) {\n    while((bytes = getOutputData()) != -1) {\n        bout.write(bytes);\n    }\n}\n<\/code><\/pre>\n<p>In this example, the <em>getOuputData()<\/em> method (its implementation is not important) returns the parts of the file that are written sequentially.<\/p>\n<h2>Writing quickly to text files using BufferedWriter<\/h2>\n<p>To write text to a file, the text must first be converted to binary data. The character-to-byte conversion is the responsibility of the class <strong><em>OutputStreamWriter<\/em><\/strong>. The class <strong><em>FileWriter<\/em><\/strong> combines <strong><em>FileOutputStream<\/em><\/strong> and <strong><em>OutputStreamWriter<\/em><\/strong>. For faster writing of files we use the class <strong><em>BufferedWriter<\/em><\/strong>, which wraps the class <strong><em>FileWriter<\/em><\/strong> and allows to use an 8 KB buffer along with an additional buffer for encoded characters.<\/p>\n<pre><code class=\"language-java\" data-line=\"\">import java.io.BufferedWriter;\nimport java.io.FileWriter;\n\nString fileName = &quot;fileName.txt&quot;;\ntry (FileWriter writer = new FileWriter(fileName);\n     BufferedWriter bufferedWriter = new BufferedWriter(writer)) {\n    String line;\n    while ((line = getLine()) != -1) {\n        bufferedWriter.write(line);\n    }\n}\n<\/code><\/pre>\n<p>In this example, the <em>getLine()<\/em> method (its implementation is not important) returns the lines of the file that are sequentially written.<\/p>\n<p>In the previous examples, we did not close the created streams. After leaving the <strong>try<\/strong> block, the <em>close()<\/em> method is automatically called to close both streams, so it is not explicitly stated or needed.<\/p>\n<h2>Conclusion<\/h2>\n<p>In this article, we have shown the most common scenarios of writing data to Java files. Smaller files that we have prepared in memory can be written using the methods of the <strong><em>Files<\/em><\/strong> class, and larger files are written in chunks using a buffer.<\/p>\n<p>If you&#8217;re a <a href=\"https:\/\/msg-life.sk\/en\/jobs\/java-programmer-senior\/\">Java developer<\/a> looking for work, check out our <a href=\"https:\/\/msg-life.sk\/en\/benefits\/\">employee benefits<\/a> and respond to our <a href=\"https:\/\/msg-life.sk\/en\/jobs\/\">job offers<\/a>!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There are many ways to Java file write. In this article, we will introduce you different classes with code examples. <\/p>\n","protected":false},"author":14,"featured_media":3023,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[57],"tags":[],"class_list":["post-3070","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-java"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/posts\/3070","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/users\/14"}],"replies":[{"embeddable":true,"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/comments?post=3070"}],"version-history":[{"count":4,"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/posts\/3070\/revisions"}],"predecessor-version":[{"id":5325,"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/posts\/3070\/revisions\/5325"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/media\/3023"}],"wp:attachment":[{"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/media?parent=3070"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/categories?post=3070"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/tags?post=3070"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}