2012-08-31 29 views
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中更好?或者任何其他方法/技术来提供更好的性能?请指教..!

+1

代码格式化... HORROR!不,但是您能否正确缩进代码?它烦人的人谁愿意帮助你争取阅读你的代码。谢谢! – thatidiotguy

回答

1

是否有任何其他方式做到这一点在Java中更好?或者其他方法或技术来提供更好的性能?

就IO性能而言,这可能是最好的,没有很多其他代码。无论如何,你将最有可能成为IO界限。

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

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

+0

非常感谢我会尽量抽出两者所花费的时间,并且会让你知道,请你能告诉我相关的内存映射文件概念有点特别在第二个程序中发生了什么。因为我正在浏览此链接http://javarevisited.blogspot.in/2012/01/memorymapped-file-and-io-in-java.html – user1633823

+0

操作系统接收一部分(或全部文件)并将其虚拟映射进入记忆。在这一点上,您可以像访问数据一样读取数据或者写入磁盘的数据。这可以显着减少复制数据的开销。另一个优点是加载在后台有效完成,如果您希望操作系统在可以写入数据时感到高兴,则不需要刷新数据。 –