问题
I frequently output text to files. I wonder something: how does BufferedWriter
work?
Does it write text on file when I call writer.write(text)
?
If it doesn't write text,do I need to use flush function to write data?
For example:
File file = new File("statistics.txt");
if (!file.exists()) {
file.createNewFile();
}
else
{
file.delete();
file.createNewFile();
}
FileWriter fileWritter = new FileWriter(file.getAbsoluteFile(),true);
BufferedWriter bufferWritter = new BufferedWriter(fileWritter);
Iterator<Map.Entry<String,Token>> it = listofTakenPairMap.entrySet().iterator();
int isim_isim=0;
int isim_fiil=0;
int zarf_fiil=0;
while (it.hasNext()) {
@SuppressWarnings("rawtypes")
Map.Entry pairs = (Map.Entry)it.next();
Token token=(Token)pairs.getValue();
String str=pairs.getKey()+ " = " +token.getCount();
if(token.getTypeOfPairofToken()==0){//isim-isim
isim_isim+=token.getCount();
}
else if(token.getTypeOfPairofToken()==1){
isim_fiil+=token.getCount();
}
else{ //zarf-fiil
zarf_fiil+=token.getCount();
}
System.out.println(str);
bufferWritter.write(str);
bufferWritter.newLine();
//it.remove(); // avoids a ConcurrentModificationException
}
bufferWritter.newLine();
bufferWritter.write("##############################");
bufferWritter.newLine();
bufferWritter.write("$isim_isim sayisi :"+isim_isim+"$");
bufferWritter.newLine();
bufferWritter.write("$isim_fiil sayisi :"+isim_fiil+"$");
bufferWritter.newLine();
bufferWritter.write("$zarf_fiil sayisi :"+zarf_fiil+"$");
bufferWritter.newLine();
bufferWritter.write("##############################");
bufferWritter.flush();
bufferWritter.close();
If an error occurs in the while loop,the file will be closed without writing data. If I use flush
function in the while loop,then why should i use BufferedWriter
? Please correct me If I'm wrong.
回答1:
By definition, a buffered writer buffers data and only writes them when it has enough in memory, to avoid too many roundtrips to the file system.
If you handle exceptions properly, and close your stream in a finally block as you should always do, the buffer will be flushed to the disk, and everything written to the buffered writer so far will be written to the disk (unless of course the exception is precisely caused by an error writing to the disk).
So, the solution is not to flush each time ou write, since it would defeat the purpose of the buffered writer. The solution is to close in a finally block (or to use the Java 7 trye-with-resources statement, which does that for you).
回答2:
Data in the streams are written to the disk in blocks. So, when you write something into your OutputStream
or Writer
, you should not expect that the server automatically persist to the disk - this is actually done very rarely. Your process is just a small process in the Virtual Machine and in the host operating system.
If you write the data to the disk, you have to wait for the Disk I/O to finish. Your code is not executed during that time, but waiting. This will increase the service time.
Also, frequent disk write (mean flush()
) will put heavy load on the system, because it cannot simply overwrite the full content of the block, but rather has to update the same block many times.
So, that's why languages like Java introduced the buffering.
To answer your question: When you write()
data, it will be buffered to a certain level (until the buffer is full). After that it will be persisted (written to the underlying Stream
, e.g. FileOutputStream
). When you call a flush()
or close()
, it will empty the buffer, so all bytes that were buffered will be written to the underlying Stream
. They also call the flush()
or close()
method of that Stream.
If an Exception
happens in the loop, you will not close the stream, so some data may be lost. Surround with try { } catch (IOException ex) {}
and close the stream properly.
回答3:
I frequently output text to files. I wonder something: how does
BufferedWriter
work?
Check the jdk's source code youself
Does it write text on file when I call writer.write(text)? If it doesn't write text, do I need to use flush function to write data?
No. Whenever you call write(String s)
, you will call: write(str, 0, str.length());
This is the source code from the source of openJDK:
218 public void write(String s, int off, int len) throws IOException {
219 synchronized (lock) {
220 ensureOpen();
221
222 int b = off, t = off + len;
223 while (b < t) {
224 int d = min(nChars - nextChar, t - b);
225 s.getChars(b, b + d, cb, nextChar);
226 b += d;
227 nextChar += d;
228 if (nextChar >= nChars)
229 flushBuffer();
230 }
231 }
232 }
233
118 /**
119 * Flushes the output buffer to the underlying character stream, without
120 * flushing the stream itself. This method is non-private only so that it
121 * may be invoked by PrintStream.
122 */
123 void flushBuffer() throws IOException {
124 synchronized (lock) {
125 ensureOpen();
126 if (nextChar == 0)
127 return;
128 out.write(cb, 0, nextChar);
129 nextChar = 0;
130 }
131 }
As you see, it will not write directly. Only when if (nextChar >= nChars)
, it will flush the buffer itself (default is private static int defaultCharBufferSize = 8192;
by using its "wrapping" class.
(In java, Java IO is design using Decorator Design Pattern. In the end, it will call the write(char[] chars, int i, int i1)
. )
If an error occurs in the while loop, the file will be closed without writing data. If I use flush function in the while loop,then why should i use
BufferedWriter
?
IO cost is VERY expensive. Unless you need to view the output "on-the-fly" (Eg view the log any time with the newest update), you should let the be done automatically the increase the performance.
来源:https://stackoverflow.com/questions/14462705/how-does-bufferedwriter-work-in-java