在java中更快地合并大文件部分
我正在编写一个JavaREST服务来支持大文件部分的并行上传。我在单独的文件中编写这些部分,并使用文件通道将它们合并。我有一个在Golang中实现的示例,它也执行相同的操作,但是当它合并各个部分时,它不需要时间。当我使用文件通道或从一个流读取并写入最终文件时,需要很长时间。我认为不同之处在于,Golang能够保持磁盘上的数据不变,只需通过不移动数据来合并它们。有没有什么方法可以在java中实现同样的功能? 这是我合并部件的代码,我对所有部件循环使用此方法:在java中更快地合并大文件部分,java,filesystems,Java,Filesystems,我正在编写一个JavaREST服务来支持大文件部分的并行上传。我在单独的文件中编写这些部分,并使用文件通道将它们合并。我有一个在Golang中实现的示例,它也执行相同的操作,但是当它合并各个部分时,它不需要时间。当我使用文件通道或从一个流读取并写入最终文件时,需要很长时间。我认为不同之处在于,Golang能够保持磁盘上的数据不变,只需通过不移动数据来合并它们。有没有什么方法可以在java中实现同样的功能? 这是我合并部件的代码,我对所有部件循环使用此方法: private void mergeF
private void mergeFileUsingChannel(String destinationPath, String sourcePath, long partSize, long offset) throws Exception{
FileChannel outputChannel = null;
FileChannel inputChannel = null;
try{
outputChannel = new FileOutputStream(new File(destinationPath)).getChannel();
outputChannel.position(offset);
inputChannel = new FileInputStream(new File(sourcePath)).getChannel();
inputChannel.transferTo(0, partSize, outputChannel);
}catch(Exception e){
e.printStackTrace();
}
finally{
if(inputChannel != null)
inputChannel.close();
if(outputChannel != null){
outputChannel.close();
}
}
}
向各国转让的文件:
许多操作系统可以直接将字节从文件系统缓存传输到目标通道,而无需实际复制它们
因此,您编写的代码是正确的,并且您看到的效率低下可能与底层文件系统类型有关
我建议的一个小优化是在模式下打开文件
位置的提升和数据的写入是否在单个原子操作中完成取决于系统
除此之外,你可能还得想办法解决这个问题。例如,首先创建一个足够大的连续文件
编辑:我还注意到您没有明确关闭FileOutputStream。最好保持并关闭它,以便关闭所有文件描述符。操作系统和文件系统类型是否与此问题相关?服务器是fedora 24。我不确定文件系统。我正在将文件传输到HDD、SSD和网络位置。因此,我尝试了几种组合,并得出结论,其操作系统和文件系统使I/O操作变慢或变快。我尝试在USB端口上连接NTFS和ext4格式的HDD,并在25秒内得到相同的结果,用于合并1GB文件的30个部分。当我在我的windows机器上的HDD上尝试同样的方法时,不到10秒。我现在正在阅读有关文件系统和操作系统如何管理I/O的文章。如果有人有好的链接可以阅读,我将不胜感激。另外,我查看了GoLang示例,它有一个技巧,它将文件的一部分合并到最终罚款,因为该部分到达服务器,而不是在最后。将此标记为已回答,因为我使用了与我所发布的相同的方法。合并的时间取决于媒体本身。java的NIO在使用channel的transferto方法进行合并方面做得很好,以避免上下文切换和缓冲区复制。我需要考虑客户端-服务器连接LAN/WAN和目标媒体类型来使用我的设置,以充分利用可用的内容,谢谢!