【问题标题】:How does BufferedWriter work in javaBufferedWriter如何在java中工作
【发布时间】:2013-01-05 22:16:43
【问题描述】:

我经常将文本输出到文件中。我想知道:BufferedWriter 是如何工作的?

当我调用writer.write(text) 时,它会在文件中写入文本吗? 如果不写文本,是否需要使用flush函数来写数据?

例如:

       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();

如果while循环发生错误,文件将被关闭而不写入数据。如果我在while循环中使用flush函数,那我为什么要使用BufferedWriter?如果我错了,请纠正我。

【问题讨论】:

  • 您是否查看了源代码以了解它的作用以及它是如何做到的?

标签: java file buffer streamwriter


【解决方案1】:

根据定义,缓冲写入器会缓冲数据,并且仅在内存足够时才写入数据,以避免与文件系统进行太多往返。

如果你正确处理异常,并像往常一样在 finally 块中关闭流,缓冲区将刷新到磁盘,并且到目前为止写入缓冲写入器的所有内容都将写入磁盘(除非当然异常正是由于写入磁盘的错误引起的)。

因此,解决方案不是每次写入时都刷新,因为它会破坏缓冲写入器的目的。解决方案是在 finally 块中关闭(或使用 Java 7 trye-with-resources 语句,它会为您执行此操作)。

【讨论】:

  • “足够的内存”是什么意思?这句话考虑了什么?
  • 一旦内存中有 N 个字符的块(IIRC 默认为 8192),它会将它们写入磁盘。在此限制之前,每次在缓冲区上调用 write() 只会将字符添加到内存缓冲区中。
【解决方案2】:

流中的数据以的形式写入磁盘。因此,当您在OutputStreamWriter 中写入内容时,您不应该期望服务器会自动保存到磁盘上——这实际上很少发生。您的进程只是虚拟机和主机操作系统中的一个小进程。

如果将数据写入磁盘,则必须等待磁盘 I/O 完成。您的代码在此期间不会执行,而是在等待。这会增加服务时间。

另外,频繁的磁盘写入(意思是flush())会给系统带来沉重的负担,因为它不能简单地覆盖块的全部内容,而是必须多次更新同一个块。

所以,这就是 Java 等语言引入缓冲的原因。

回答你的问题:当你write()数据时,它会被缓冲到一定的水平(直到缓冲区满)。之后它将被持久化(写入底层Stream,例如FileOutputStream)。当您调用flush()close() 时,它将清空缓冲区,因此所有缓冲的字节都将写入底层Stream。他们还调用该 Stream 的 flush()close() 方法。

如果循环中发生Exception,您将不会关闭流,因此可能会丢失一些数据。用try { } catch (IOException ex) {}包围并正确关闭流。

【讨论】:

    【解决方案3】:

    我经常将文本输出到文件中。我想知道:如何 BufferedWriter工作?

    检查jdk's source code你自己

    当我调用 writer.write(text) 时,它会在文件上写入文本吗?如果它 不写文本,需要用flush函数写数据吗?

    没有。每当你调用write(String s),你就会调用:write(str, 0, str.length());这是来自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     }    
    

    如你所见,它不会直接写。只有在if (nextChar &gt;= nChars) 时,它才会刷新缓冲区本身(默认为private static int defaultCharBufferSize = 8192;,使用其“包装”类。 (在java中,Java IO is design using Decorator Design Pattern。最后会调用write(char[] chars, int i, int i1)。)

    如果while循环发生错误,文件会直接关闭 写入数据。如果我在while循环中使用flush函数,那为什么 我应该使用BufferedWriter 吗?

    IO 成本非常昂贵。除非您需要“即时”查看输出(例如随时查看最新更新的日志),否则您应该让它自动完成以提高性能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-29
      • 2014-09-25
      • 2012-02-05
      • 1970-01-01
      相关资源
      最近更新 更多