【问题标题】:Regarding reading a file and optimizing the performance关于读取文件和优化性能
【发布时间】:2012-08-31 17:32:30
【问题描述】:

我正在对 IO 进行一些研究,并阅读了以下有关缓冲技术的文章。为了最大限度地减少底层操作系统的磁盘访问和工作,缓冲技术使用一个临时缓冲区,它以分块方式读取数据,而不是在每次读取操作时直接从磁盘读取数据。

给出了没有缓冲和有缓冲的例子。

没有缓冲:

try 
{ 
  File f = new File("Test.txt");
  FileInputStream fis = new FileInputStream(f);
  int b; int ctr = 0; 

  while((b = fis.read()) != -1) 
  { 
    if((char)b== '\t') 
    { 
      ctr++; 
    } 
  } 
  fs.close();
 // not the ideal way
 } catch(Exception e)
 {}

带缓冲:

try
{
  File f = new File("Test.txt");
  FileInputStream fis = new FileInputStream(f);
  BufferedInputStream bs = new BufferedInputStream(fis);
  int b;
  int ctr = 0;
  while((b =bs.read()) != -1)
  {
    if((char)b== '\t')
    {
      ctr++;
    }
  }
  fs.close(); // not the ideal way
}
catch(Exception e){}

结论是:

Test.txt was a 3.5MB  file 
Scenario 1 executed between 5200 to 5950 milliseconds for 10 test runs 
Scenario 2 executed between 40 to 62 milliseconds for 10 test runs.

在 Java 中还有其他更好的方法吗?或任何其他方法/技术来提供更好的性能?请指教..!

【问题讨论】:

  • 代码格式……太可怕了!不,但你能正确缩进代码吗?对于那些想帮助你努力阅读你的代码的人来说,这很烦人。谢谢!

标签: java io


【解决方案1】:

在 Java 中还有其他更好的方法吗?或任何其他提供更好性能的方法/技术?

就 IO 性能而言,如果没有很多其他代码,这可能是最好的。无论如何,您很可能会受到 IO 限制。

while((b =bs.read()) != -1)

逐字节读取是非常低效的。如果您正在阅读文本文件,那么您应该改用BufferedReader。这会将字节数组转换为String

BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
...
while ((String line = reader.readLine()) != null) {
   ...
}

此外,对于任何 IO,您应该始终在 try/finally 块中执行它以确保关闭它:

FileInputStream fis = new FileInputStream(f);
BufferedReader reader;
try {
    reader = new BufferedReader(new InputStreamReader(fis));
    // once we wrap the fis in a reader, we just close the reader
} finally {
    if (reader != null) {
       reader.close();
    }
    if (fis != null) {
       fis.close();
    }
}

【讨论】:

    【解决方案2】:

    您的代码的问题是您正在按字节读取文件(每个请求一个字节)。将其逐块读取到数组中 - 使用 Buffer 时性能将等于 1。

    您可能还想尝试 NIO 和内存映射文件,请参阅 http://www.linuxtopia.org/online_books/programming_books/thinking_in_java/TIJ314_029.htm

    【讨论】:

      【解决方案3】:

      您可以一次读取数据块,这仍然比使用缓冲输入更快。

      FileInputStream fis = new FileInputStream(new File("Test.txt"));
      int len, ctr = 0;
      byte[] bytes = new byte[8192];
      
      while ((len = fis.read(bytes)) > 0)
          for (int i = 0; i < len; i++)
              if (bytes[len] == '\t')
                  ctr++;
      fis.close();
      

      你也可以试试内存映射。

      FileChannel fc = new FileInputStream(new File("Test.txt")).getChannel();
      ByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
      int ctr = 0;
      for (int i = 0; i < bb.limit(); i++)
          if (bb.get(i) == '\t')
              ctr++;
      fc.close();
      

      我希望这两个选项的速度大约是原来的两倍。

      【讨论】:

      • 非常感谢,我会尽量抽出两者所花费的时间并告诉你,你能告诉我一些相关的内存映射文件概念,特别是在第二个程序中发生了什么..当我通过这个链接javarevisited.blogspot.in/2012/01/…
      • 操作系统获取一部分(或所有文件)并将其虚拟映射到内存中。此时,您可以访问数据,就好像它已被读入内存或可写写入磁盘一样。这可以显着减少复制数据的开销。另一个优点是加载是在后台有效完成的,如果您愿意让操作系统在可以写入数据时写入数据,则无需刷新数据。
      猜你喜欢
      • 1970-01-01
      • 2012-01-31
      • 1970-01-01
      • 2013-04-02
      • 2011-11-08
      • 2016-08-16
      • 1970-01-01
      • 1970-01-01
      • 2019-12-28
      相关资源
      最近更新 更多