Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to append/write huge data file text in Java

Tags:

java

file

I have a database with 150k records. I want to write this to file as fast as possible. I've tried many approaches, but all seem slow. How do I make this faster?

I read these records in blocks of 40k. So first I read 40k then another 40k and so on.

After reading the records, this process returns a StringBuilder which contains 40k lines. Then we write this StringBuilder to a file.

private static void write(StringBuilder sb, Boolean append) throws Exception {
    File file = File.createTempFile("foo", ".txt");

    FileWriter writer = new FileWriter(file.getAbsoluteFile(), append);
    PrintWriter out = new PrintWriter(writer);
    try {
        out.print(sb);           
        out.flush();
        writer.flush();
    } finally {
        writer.close();
        out.close();
    }
}

I read this other example but it is equally slow: Fastest way to write huge data in text file Java

I also tried it with NIO api:

private static void write(StringBuilder sb, Boolean append)) throws Exception {
    FileChannel rwChannel = new FileOutputStream("textfile.txt", true).getChannel();
    ByteBuffer bb = ByteBuffer.wrap(sb.toString().getBytes("UTF-8"));
    rwChannel.write(bb);
    rwChannel.close();
}

Which is the best method to write/append huge data into file?

like image 685
hudi Avatar asked Sep 10 '13 12:09

hudi


People also ask

How do you append a text file in Java?

In Java, we can append a string in an existing file using FileWriter which has an option to open a file in append mode. Java FileWriter class is used to write character-oriented data to a file. It is a character-oriented class that is used for file handling in Java.

How read and write large files in Java?

Using BufferedReader and Java Streams To do that, we will use BufferedReader, which provides a Stream of strings read from the file. Next is an example of using Java Stream provided by BufferedReader to process a very very large file (10GB). Now, we will test the method that uses BufferedReader to read a 10GB file.

How do you append data to a file?

If you are working on text data and the number of write operations is less, use FileWriter and use its constructor with append flag value as true . If the number of write operations is huge, you should use the BufferedWriter. To append binary or raw stream data to an existing file, you should use FileOutputStream.

How do you append a file to another file in Java?

When creating a FileWriter object, we pass the path of the file and true as the second parameter. true means we allow the file to be appended. Then, we use write() method to append the given text and close the filewriter.


2 Answers

You don’t need a PrintWriter here. If you have whatever kind of Writer (e.g. a FileWriter) you can simply invoke append(sb) on it. And you don’t need to flush, close implies flushing.

private static void write(StringBuilder sb, Boolean append) throws Exception {
  File file = File.createTempFile("foo", ".txt");

  try(FileWriter writer = new FileWriter(file.getAbsoluteFile(), append)) {
      writer.append(sb);
  }
}

On my system I encountered a small performance improvement using a Channel rather than an OutputStream:

private static void write0a(StringBuilder sb, Boolean append) throws Exception {
  File file = File.createTempFile("foo", ".txt");

  try(Writer writer = Channels.newWriter(new FileOutputStream(
      file.getAbsoluteFile(), append).getChannel(), "UTF-8")) {
    writer.append(sb);
  }
}

However these are only slight improvements. I don’t see much possibilities here as all the code ends up calling the same routines. What could really improve your performance is keeping the Writer alive during the invocations and not flushing every record.

like image 194
Holger Avatar answered Oct 17 '22 00:10

Holger


If you have a huge amount of data, it's better that you don't store it to StringBuilder and then write it to file at once.

This is the best scenario:

1) Before you start process on the data create FileInputStream

FileOutputStream fos = new FileOutputStream("/path/of/your/file");

2) Create and OutputStreamWriter from this file

OutputStreamWriter w = new OutputStreamWriter(fos, "UTF-8");

3) Create BufferedWriter (Improve file writing performance)

BufferedWriter bw = new BufferedWriter(w);

4) Pass bw to your process function and then flush/close

bw.flush();
bw.close();

The functionality of StringBuilder and BufferedWriter is almost same, So you do not need to change your code so much. The only negative point of this scenario is that, your process will involve all the time that the data are writing to file, but if you don't process the data in different thread, it is not an issue.

In this way, it doesn't matter how large data is it

like image 32
user1079877 Avatar answered Oct 17 '22 01:10

user1079877