Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does java.io.FileWriter buffer bytes before writing to the output stream

As per java docs,

In general, a Writer sends its output immediately to the underlying character or byte stream. Unless prompt output is required, it is advisable to wrap a BufferedWriter around any Writer whose write() operations may be costly, such as FileWriters and OutputStreamWriters. For example,

PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));

will buffer the PrintWriter's output to the file. Without buffering, each invocation of a print() method would cause characters to be converted into bytes that would then be written immediately to the file, which can be very inefficient.

But the following code appears as though FileWriter also buffers bytes before flushing to the output stream.

 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;


 public class TestFileWriter {
 /**
 * @param args
 * @throws IOException 
 */
public static void main(String[] args) throws IOException {
    FileWriter fileWriter= new FileWriter("test.txt");
    File file=new File("test.txt");
    for (int i=0; i<1000; i++) {
        fileWriter.write("a very long string, a very long string, a very long string, a very long string, a very long string\n");
        if(i%50 == 0)
            System.out.print("file size=" +  file.length()+",");

    }
    fileWriter.close();
    System.out.println("file size=" +  file.length());

}

}

Output :-

file size=0,file size=0,file size=8192,file size=8192,file size=16384,file size=24576,file size=24576,file size=32768,file size=32768,file size=40960,file size=49152,file size=49152,file size=57344,file size=57344,file size=65536,file size=73728,file size=73728,file size=81920,file size=81920,file size=90112,file size=99000

Why isn't the data being written to the file as and when it is being written ?

like image 638
Kumaran Avatar asked Feb 13 '23 02:02

Kumaran


1 Answers

If you add

fileWriter.flush();

you can see the sizes have changed on each line. This means buffering is occurring.

Using the debugger I traced this to the StreamEncoder which doesn't have source in the Oracle JDK but is available on line

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/sun/nio/cs/StreamEncoder.java

private static final int DEFAULT_BYTE_BUFFER_SIZE = 8192;

private StreamEncoder(OutputStream out, Object lock, CharsetEncoder enc) {
    // some deleted
    if (ch == null) {
        bb = ByteBuffer.allocate(DEFAULT_BYTE_BUFFER_SIZE);
    }
}

As you can see, the encoder has it's own buffer.

Note: since this is an internal class it may change in the future and it might not behave this way on all platforms.

like image 164
Peter Lawrey Avatar answered Apr 29 '23 22:04

Peter Lawrey