0

我正在对 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中还有其他更好的方法吗?或任何其他方法/技术来提供更好的性能?请指教..!

4

3 回答 3

1

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

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

于 2012-08-31T17:38:17.750 回答
1

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

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

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

逐字节读取是非常低效的。如果您正在阅读文本文件,那么您应该使用 aBufferedReader代替。这会将字节数组转换为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();
    }
}
于 2012-08-31T18:22:47.763 回答
0

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

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

我希望这两个选项的速度都快两倍。

于 2012-08-31T19:13:37.543 回答