编写巨大的文件和Java堆空间
我正试图将一个500mb到1.5GB之间的大文件写入磁盘。 我使用编写巨大的文件和Java堆空间,java,file,exception,client-server,Java,File,Exception,Client Server,我正试图将一个500mb到1.5GB之间的大文件写入磁盘。 我使用zipOutputStream将其压缩,然后通过网络发送 但在客户端,当我试图解压和 写它,它给我Java堆空间。exception try (FileOutputStream fos = new FileOutputStream(outFile)) { int fileLength = (int)zipEntry.getSize(); byte[] fileB
zipOutputStream
将其压缩,然后通过网络发送
但在客户端,当我试图解压和
写它,它给我Java堆空间。
exception
try (FileOutputStream fos = new FileOutputStream(outFile)) {
int fileLength = (int)zipEntry.getSize();
byte[] fileByte = new byte[fileLength];
zips.read(fileByte);
fos.write(fileByte);
}
我知道一个字节数组的内存分配相当大,但我怎么可能修复它呢?您正在制作的
字节[]
数组是您的缓冲区,在从输入流
传输到输出流时,缓冲区充当堆中的临时位置。除非您希望程序在内存中使用500mb-1.5gb,否则您需要减小缓冲区大小。下面是我用于执行此操作的常用方法。这种方法使用1kb的缓冲区,您可以根据大小来选择最适合您的缓冲区
/**
* writes all bytes from inputStream to outputStream
* @param source
* @param destination
* @throws IOException
*/
public static void pipeStreams(java.io.InputStream source, java.io.OutputStream destination) throws IOException {
// 1kb buffer
byte [] buffer = new byte[1024];
int read = 0;
while((read=source.read(buffer)) != -1) {
destination.write(buffer, 0, read);
}
destination.flush();
}
使用此方法的代码如下所示
try (FileOutputStream fos = new FileOutputStream(outFile)) {
pipeStreams(zips, fos);
}
您可以使用Files.copy(zips,outFile.toPath())完成相同的任务,而不是一次将整个文件读入内存代码>。Files.copy方法的文档是。您可以一次读取/写入部分文件。这就是流的设计用途。你一次读/写8K怎么样?@PeterLawrey如何分配流的大小?你也可以用文件来完成同样的事情。copy(zips,outFile.toPath())代码>。看到了吗?@VGR想把它变成一个答案吗?wekk用了将近2分钟的时间来传输文件,我被困在了如何使它只读取几个KB的部分中,而你给我看了。谢天谢地,我想知道缓冲区大小,例如10KB,是否意味着spead是10X?哦,我的打字错误,我的意思是速度我知道答案是不,但是,在这种情况下,我们定义一个缓冲区,使用最大可能空间来缓冲,而不是小的1KB缓冲区怎么样?@lonesome最有可能的瓶颈是你的下载速度。只有当您看到高CPU利用率(忽略系统时间)时,它才表明更大的缓冲区可能会有所帮助。顺便说一句,您自己尝试这样做并没有坏处。试试4KB、16KB、64KB等等,看看你是否认为这会有所不同。那么,你认为哪种方式更好?缓冲还是这个复制方法?文件。copy
更好,因为使用它可读性更好,而且我相信它目前有自己的缓冲,所以肯定不会比自己做的更糟。我使用文件时堆空间仍然不足。copy。。。有没有办法用这个来指定缓冲区大小?@Rimer我需要看看你的代码。除非您试图将整个文件读入ByteArrayOutputStream或其他文件,否则不可能耗尽空间。我知道我已经使用files.copy复制了3 GB文件,没有任何问题。我的错误我在堆空间不足时运行了错误的代码分支。文件复制成功了!它使用一个8KB的缓冲区,顺便说一句,我从源代码窥探中发现。。。