2017-05-04 74 views
-6

这个问题很短。 我有一个文件阅读3GB文件无例外

Datei.trec-3,99 GB,我使用此代码阅读:

public class Main { 
    public static void main(String[] args) { 
     byte[] content = null; 
     try { 
      content = Files.readAllBytes(Paths.get("D:", "Videos","Captures","Datei.trec")); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     System.out.println(content); 
    } 
} 

,这是输出:

Exception in thread "main" java.lang.OutOfMemoryError: Required array size too large 
    at java.nio.file.Files.readAllBytes(Unknown Source) 
    at Main.main(Main.java:13) 

所以是有一个没有异常写入数组的选项(FileInputStream等)?

+0

内容是一个有限的大小的数组,你是溢出.... –

+0

我知道,但我应该如何阅读内容呢? – Niton

+3

你会流它。读取一些数据,做你需要的东西,读下一个位等 – pandaadb

回答

3

的问题是,以容纳所有这些数据所需要的阵列比MAX_BUFFER_SIZE更大,这是在定义java.nio.FilesInteger.MAX_VALUE - 8

public static byte[] readAllBytes(Path path) throws IOException { 
     try (SeekableByteChannel sbc = Files.newByteChannel(path); 
      InputStream in = Channels.newInputStream(sbc)) { 
      long size = sbc.size(); 
      if (size > (long)MAX_BUFFER_SIZE) 
       throw new OutOfMemoryError("Required array size too large"); 

      return read(in, (int)size); 
     } 
    } 

这是必要的,因为数组通过整数进行索引 - 这是您可以获得的最大数组。

你有三个选择:

流通过文件

也就是说,打开文件,读取块,处理它,阅读另一块,对它进行处理,一次又一次,直到你”已经经历了整个事情。

Java提供了很多类来执行此操作:InputStream,Reader,Scanner等 - 它们在大多数Java入门课程和书籍中都有讨论。研究其中之一。

https://stackoverflow.com/a/21706141/7512

这样做的有效性取决于你能够做一些有意义的事情与文件的早期部分,不知道将会发生什么。很多时候都是这样。其他时候,您必须在文件中进行多次传递。

文件格式通常被设计为可以一次完成处理 - 根据这个设计自己的文件格式是一个不错的主意。

我注意到你的文件是一个.trec文件,它是一个屏幕捕获的视频。视频和音频格式很可能是为流媒体而设计的 - 这是您可以在下载结束之前观看YouTube视频的开始的原因。

内存映射

如果你真的需要跳来跳去的文件来处理它的内容,你可以作为一个内存映射文件打开它。

查看RandomAccessFile的文档 - 这为您提供了一个seek()方法的对象,因此您可以读取文件数据中的任意点。

阅读到多个阵列

我包括这仅出于完整性;将整个文件整理成堆内存很难。但如果你真的想,你可以将这些字节存储在一些数组中 - 也许是List<byte[]>。 Java-ish伪代码:

List<byte[]> filecontents = new ArrayList<byte[]>(); 
    InputStream is = new FileInputStream(...); 
    byte[] buffer = new byte[MAX_BUFFER_SIZE]; 
    int bytesGot = readUpToMaxBufferSizeFrom(file); 
    while(bytesGot != -1) { 
     byte[] chunk = new byte[bytesGot]; 
     System.arrayCopy(buffer, 0, chunk, 0, bytesGot); 
     filecontents.add(chunk); 
    } 

这允许你达到MAX_BUFFER_SIZE * Integer.MAX_INTEGER字节。访问内容比使用简单的数组稍微复杂一点 - 但是实现细节可以隐藏在类中。

你会的,当然,需要配置的Java有一个巨大的堆大小 - 见How to set the maximum memory usage for JVM?

不要这样做。

+1

道歉,增加堆大小无助于 - 删除该部分,并解释了关于'MAX_BUFFER_SIZE' – slim

+0

感谢您的答复 – Niton

0

我建议你通过文件流;可以使用例如LineIterator,从Apache的百科全书:

LineIterator it = FileUtils.lineIterator(theFile, "UTF-8"); 
try { 
    while (it.hasNext()) { 
     String line = it.next(); 
    } 
} finally { 
    LineIterator.closeQuietly(it); 
} 
+0

我需要收集一个变量中的全部内容(数组或数据类型) – Niton