【问题标题】:Java difference between FileWriter and BufferedWriterFileWriter和BufferedWriter之间的Java区别
【发布时间】:2012-09-03 05:37:53
【问题描述】:

它们之间有什么区别?我只是在学习 Java ATM,但似乎我可以双向写入文件,即(我没有在这里复制 try-catch 块。)

FileWriter file = new FileWriter("foo.txt");
file.write("foobar");
file.close();

FileWriter file = new FileWriter("foo.txt");
BufferedWriter bf = new BufferedWriter(file);
bf.write("foobar");
bf.close();

我理解了先缓存数据的概念,那是不是说第一个例子一个一个地写入字符,第二个先把它缓冲到内存中再写入一次呢?

【问题讨论】:

    标签: java file-io java-io


    【解决方案1】:

    在无缓冲的输入/输出(FileWriter,FileReader)中,读取或写入请求由底层操作系统直接处理。 https://hajsoftutorial.com/java/wp-content/uploads/2018/04/Unbuffered.gif

    这会使程序的效率大大降低,因为每个此类请求通常都会触发磁盘访问、网络活动或其他一些相对昂贵的操作。为了减少这种开销,Java 平台实现了缓冲的 I/O 流。 BufferedReader 和 BufferedWriter 类提供内部字符缓冲区。写入缓冲写入器的文本存储在内部缓冲区中,并且仅在缓冲区填满或刷新时才写入底层写入器。 https://hajsoftutorial.com/java/wp-content/uploads/2018/04/bufferedoutput.gif

    更多https://hajsoftutorial.com/java-bufferedwriter/

    【讨论】:

      【解决方案2】:

      如果你这样做,BufferedWriter 会更高效

      • 在刷新/关闭之间有多次写入
      • 与缓冲区大小相比,写入量很小。

      在您的示例中,您只有一次写入,因此 BufferedWriter 只会增加您不需要的开销。

      这是否意味着第一个示例将字符一个接一个地写入,第二个示例将其缓冲到内存并写入一次

      在这两种情况下,字符串都是一次写入的。

      如果你只使用 FileWriter 你的 write(String) 调用

       public void write(String str, int off, int len) 
              // some code
              str.getChars(off, (off + len), cbuf, 0);
              write(cbuf, 0, len);
       }
      

      这会进行一次系统调用,每次调用 write(String)。


      BufferedWriter 提高效率的地方在于多次小写。

      for(int i = 0; i < 100; i++) {
          writer.write("foorbar");
          writer.write(NEW_LINE);
      }
      writer.close();
      

      如果没有 BufferedWriter,这可能会进行 200 (2 * 100) 次系统调用并写入磁盘,这是低效的。使用 BufferedWriter,这些都可以一起缓冲,并且由于默认缓冲区大小为 8192 个字符,因此这只需 1 个系统调用即可写入。

      【讨论】:

      • 我有一个问题,当我使用 FileWriter 时,write 返回后,java 是否保证内容在磁盘中刷新或仅在页面缓存中,哪个操作系统会在需要时刷新?
      • @Jaskey 如果你使用无缓冲的 FIleWriter,write() 表示操作系统有一个副本,最终应该写入磁盘。
      【解决方案3】:

      http://docs.oracle.com/javase/1.5.0/docs/api/java/io/BufferedWriter.html

      通常,Writer 将其输出立即发送到底层字符或字节流。除非需要快速输出,否则建议将 BufferedWriter 包装在任何 write() 操作可能成本高昂的 Writer 周围,例如 FileWriters 和 OutputStreamWriters。例如,

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

      会将 PrintWriter 的输出缓冲到文件中。如果没有缓冲,每次调用 print() 方法都会导致字符转换为字节,然后立即写入文件,这可能非常低效。

      【讨论】:

        【解决方案4】:

        来自 Java API 规范:

        FileWriter

        编写字符文件的便利类。该类的构造函数假定默认字符编码和默认字节缓冲区大小是可以接受的。

        BufferedWriter

        将文本写入字符输出流,缓冲字符,以便高效写入单个字符、数组和字符串。

        【讨论】:

          【解决方案5】:

          你是对的。以下是BufferedWriterwrite() 方法的外观:

          public void write(int c) throws IOException {
              synchronized (lock) {
                  ensureOpen();
                  if (nextChar >= nChars)
                      flushBuffer();
                  cb[nextChar++] = (char) c;
              }
          }
          

          如您所见,它确实会检查缓冲区是否已满 (if (nextChar &gt;= nChars)) 并刷新缓冲区。然后它将新字符添加到缓冲区 (cb[nextChar++] = (char) c;)。

          【讨论】:

            【解决方案6】:

            BufferedWriter 效率更高。如果内存正确地为我服务,它会保存小的写入和写入一个更大的块。如果你正在做很多小写,那么我会使用 BufferedWriter。调用操作系统的写入调用速度很慢,因此通常需要尽可能少的写入。

            【讨论】:

              猜你喜欢
              • 2019-06-08
              • 1970-01-01
              • 2013-07-27
              • 2018-04-16
              • 2012-12-13
              • 2012-03-05
              • 2012-01-21
              • 2016-06-29
              相关资源
              最近更新 更多