这个问题非常简短。 我有一个文件
Datei.trec-3,99 GB ,我用以下代码阅读:
orient
这是输出:
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) {
e.printStackTrace();
}
System.out.println(content);
}
}
有没有办法在没有异常的情况下读取数组(Streams等)? 该文件小于允许的HEAP,因此应该可以在程序中一次存储所有数据。
答案 0 :(得分:4)
问题是保存所有数据所需的数组大于MAX_BUFFER_SIZE
,java.nio.Files
定义为Integer.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 :(得分:0)
我建议你流式传输文件;您可以使用例如来自Apache Commons的LineIterator:
LineIterator it = FileUtils.lineIterator(theFile, "UTF-8");
try {
while (it.hasNext()) {
String line = it.next();
}
} finally {
LineIterator.closeQuietly(it);
}