当前位置: 首页 > 知识库问答 >
问题:

BufferedWriter在java中是如何工作的

周辉
2023-03-14

我经常把文本输出到文件中。我想知道: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?如果我错了,请纠正我。

共有3个答案

赵灼光
2023-03-14

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

自己检查jdk的源代码

当我打电话给writer时,它会把文本写入文件吗。写(短信)?如果它不写文本,我需要使用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

如果while循环中发生错误,文件将在不写入数据的情况下关闭。如果我在while循环中使用flush函数,那么为什么要使用BufferedWriter

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

闻人栋
2023-03-14

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

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

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

所以,这就是为什么像Java这样的语言引入了缓冲。

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

如果循环中发生异常,则不会关闭流,因此可能会丢失一些数据。用环绕尝试{}捕获(IOExc0019 ex){}并正确关闭流。

阴波峻
2023-03-14

根据定义,缓冲写入程序缓冲数据,并仅在内存足够时写入数据,以避免对文件系统进行过多的往返。

如果您正确处理异常,并像您应该做的那样在最终块中关闭您的流,缓冲区将被刷新到磁盘,到目前为止写入缓冲写入器的所有内容都将被写入磁盘(当然,除非异常精确地由写入磁盘的错误引起)。

因此,解决方案不是每次写入时都刷新,因为这样会破坏缓冲写入程序的功能。解决方案是在finally块中关闭(或者使用Java7TRYE with resources语句,它会为您完成这一任务)。

 类似资料:
  • null null 它如何记住字符串和double,加宽/上转换应该记住超类的状态和方法。 如何访问子类类型和值?

  • 问题内容: 我正在查看源代码,并且看到了此方法: 当此方法可以返回时,我不明白它是如何工作的? 问题答案: 该方法可以对某些操作返回 true ,例如: 基本上,代表一个未定义的值。值是,和。这似乎是合乎逻辑的,因为它也给了您。 请参阅的javadoc : 它等效于返回的值 然后: 如果参数是在范围内的任何值通过或在范围通过,其结果是一个。Java提供的IEEE 754浮点运算无法区分具有不同位模

  • 我熟悉传统的线程实现,但对Executorservice不太确定。我知道当使用executor服务处理线程时,它非常方便。但我对它的实现有点困惑。 假设我有一个父线程/主线程和一个最大线程池大小为10的执行器服务。现在,我只想在jms队列的大小小于1000的情况下对其执行特定任务。所以现在我可以考虑用两种方式来实现这一点。 案例1: 案例2: 我的理解是案例2不会跨越多个线程。我是否正确?或者有其

  • 在Spark中是如何工作的? 如果我们注册一个对象作为一个表,会将所有数据保存在内存中吗?

  • 我从网上和论坛上看到了关于BatchSize的相关主题,但我仍然不明白一些部分。所以让我们描述一下我理解的和不理解的。 批量取数:选择取数的优化策略。Hibernate通过指定主键或外键列表,在一次选择中检索一批实体实例或集合。 让我们有JPA 2.0,带有Hibernate实现。这些实体: } 因此,我懒得去了解产品中的制造商。因此,当我执行select fetching时,就完成了。所以我有很

  • 我的项目中的三个模型对象(本文末尾的模型和存储库片段)之间确实存在关系。 当我调用时,它会触发三个select查询: (“sql”) (对我来说)那是相当不寻常的行为。在阅读Hibernate文档后,我认为它应该始终使用连接查询。当类中的更改为时,查询没有区别(使用附加选择进行查询),当更改为时,城市类的查询也一样(使用JOIN进行查询)。 当我使用抑制火灾时,有两种选择: 我的目标是在所有情况下