更快的方式来读取文件

时间:2011-05-02 08:11:14

标签: java performance file-io

我正在开发一个包含大约400个输入文件和大约40个输出文件的程序。 它很简单:它读取每个输入文件,并生成一个新文件但更大(基于算法)。

我正在使用BufferedReader中的read()方法:

String encoding ="ISO-8859-1";
FileInputStream fis = new FileInputStream(nextFile);
BufferedReader reader = new BufferedReader(new InputStreamReader(fis, encoding));
char[] buffer = new char[8192] ;

要读取我正在使用的输入文件:

private String getNextBlock() throws IOException{
    boolean isNewFile = false;

    int n = reader.read(buffer, 0, buffer.length);
    if(n == -1) {
        return null;
    } else {
        return new String(buffer,0,n);
    }
}

对于每个块,我正在进行一些检查(比如查看块内部的一些字符串),然后我将其写入文件中:

BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
        new FileOutputStream("fileName"), encoding));

writer.write(textToWrite);

问题在于它需要大约12分钟。 我想要更快地找到别的东西。 任何人都对某些事情有了更好的了解吗?

感谢。

3 个答案:

答案 0 :(得分:20)

你应该可以在这里找到答案:

http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quickly

要获得最佳的Java读取性能,需要记住四件事:

  • 通过一次读取数组来最小化I / O操作,而不是一次读取一个字节。一个8K字节的阵列是一个很好的大小。

  • 通过一次获取数据数组来最小化方法调用,而不是一次获取一个字节。使用数组索引来获取数组中的字节数。

  • 如果您不需要线程安全,请最小化线程同步锁。对线程安全类进行较少的方法调用,或者使用非线程安全的类,如FileChannel和MappedByteBuffer。

  • 最大限度地减少JVM / OS,内部缓冲区和应用程序阵列之间的数据复制。将FileChannel与内存映射一起使用,或使用直接或包装的数组ByteBuffer。

答案 1 :(得分:4)

由于您没有提供太多详细信息,我可能会提示您尝试使用内存映射文件:

FileInputStream f = new FileInputStream(fileName);
FileChannel ch = f.getChannel( );
MappedByteBuffer mbb = ch.map( ch.MapMode.READ_ONLY, 0L, ch.size( ) );
while ( mbb.hasRemaining( ) )  {
      // Access the data using the mbb
}

如果您想详细说明您的文件包含哪种数据,则可以对其进行优化。

修改

//使用mbb访问日期在哪里,您对文本进行冷解码:

String charsetName = "UTF-16"; // choose the apropriate charset.
CharBuffer cb =  Charsert.forName(charsetName).decode(mbb);
String text = cb.toString();

答案 2 :(得分:1)

映射字节缓冲区是最快的方法:

 FileInputStream f = new FileInputStream( name );
FileChannel ch = f.getChannel( );
MappedByteBuffer mb = ch.map( ch.MapMode.READ_ONLY,
    0L, ch.size( ) );
byte[] barray = new byte[SIZE];
long checkSum = 0L;
int nGet;
while( mb.hasRemaining( ) )
{
    nGet = Math.min( mb.remaining( ), SIZE );
    mb.get( barray, 0, nGet );
    for ( int i=0; i<nGet; i++ )
    checkSum += barray[i];
}