2012-02-01 37 views
10

用Java的I/O方法读取相对较大的文件可能是最快的方法是什么?我当前的解决方案使用BufferedInputStream保存到分配有1024字节的字节数组中。每个缓冲区都保存在ArrayList以备后用。整个过程通过一个单独的线程(可调用接口)调用。在Java中读取相对较大的字节文件的最快方法

虽然不是很快。

ArrayList<byte[]> outputArr = new ArrayList<byte[]>();  
    try { 
     BufferedInputStream reader = new BufferedInputStream(new FileInputStream (dir+filename)); 

     byte[] buffer = new byte[LIMIT]; // == 1024 
      int i = 0; 
      while (reader.available() != 0) { 
       reader.read(buffer); 
       i++; 
       if (i <= LIMIT){ 
        outputArr.add(buffer); 
        i = 0; 
        buffer = null; 
        buffer = new byte[LIMIT]; 
       } 
       else continue;    
      } 

     System.out.println("FileReader-Elements: "+outputArr.size()+" w. "+buffer.length+" byte each."); 
+0

查看Apache Commons库以获取更多选项。为了确定速度,请看O'Reilly的Java Performance Tuning一书。 – therobyouknow 2012-02-01 10:03:07

+5

目前,您正在忽略read()调用返回的值。 *不要那样做。* – 2012-02-01 10:06:34

回答

25

我会使用一个内存映射文件,它足够快,可以在同一个线程中执行。

final FileChannel channel = new FileInputStream(fileName).getChannel(); 
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); 

// when finished 
channel.close(); 

这假设文件小于2 GB,并且需要10毫秒或更少。

+1

血腥地狱!为什么这件事太快了?无论如何,完美的作品。 (编辑:它从内存中获取文件,java文档只是告诉我。聪明) – 2012-02-01 15:42:39

+1

如果你需要访问超过2 GB的数据,你需要使用多个映射。 – 2012-02-01 21:42:11

3

请勿使用available():这不可靠。并且不要忽略read()方法的结果:它会告诉您实际读取的字节数。如果你想读内存中的所有,使用一个ByteArrayOutputStream,而不是使用List<byte[]>

ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
int read; 
while ((read = reader.read(buffer)) >= 0) { 
    baos.write(buffer, 0, read); 
} 
byte[] everything = baos.toByteArray(); 

我觉得1024有点小为缓冲大小。我会使用更大的缓冲区(类似于16 KB或32 KB)

请注意,Apache commons IO和Guava具有为您实现此目的的实用方法,并且已经进行了优化。

1

查看Java NIO(非阻塞输入/输出)API。此外,this question可能被证明是有用的。

我没有太多的IO经验,但我听说NIO是更有效的方式处理大型数据集。

相关问题