我已经实现了以下代码来复制文件(二进制文件) 代码
private void copyFileWithChannels(File aSourceFile, File aTargetFile) {
log("Copying files with channels.");
FileChannel inChannel = null;
FileChannel outChannel = null;
FileInputStream inStream = null;
FileOutputStream outStream = null;
try {
inStream = new FileInputStream(aSourceFile);
inChannel = inStream.getChannel();
outStream = new FileOutputStream(aTargetFile);
outChannel = outStream.getChannel();
long bytesTransferred = 0;
while(bytesTransferred < inChannel.size()){
bytesTransferred += inChannel.transferTo(0, inChannel.size(), outChannel);
}
}
catch(FileNotFoundException e){
log.error("FileNotFoundException in copyFileWithChannels()",e);
}
catch (IOException e) {
log.error("IOException in copyFileWithChannels()",e);
}
catch (Exception e) {
log.error("Exception in copyFileWithChannels()",e);
}
finally {
try{
if (inChannel != null) inChannel.close();
if (outChannel != null) outChannel.close();
if (inStream != null) inStream.close();
if (outStream != null) outStream.close();
}catch(Exception e){
log.error("Exception in copyFileWithChannels() while closing the stream",e);
}
}
}
我有一个zip文件的测试代码。当我验证文件时,我发现生成的文件已损坏(大小增加)。 源zip文件大约是9GB。
答案 0 :(得分:2)
试试这个:
while(bytesTransferred < inChannel.size()){
bytesTransferred += inChannel.transferTo(bytesTransferred, inChannel.size() - bytesTransferred, outChannel);
}
另外,我将引用IOUtils实现作为参考
https://github.com/apache/commons-io/blob/master/src/main/java/org/apache/commons/io/FileUtils.java
具体地
private static void doCopyFile(final File srcFile, final File destFile, final boolean preserveFileDate)
答案 1 :(得分:1)
transferTo
方法的第一个参数给出了传输的位置,而不是相对于流停止的位置,而是相对于文件的开头。由于您将0
放在那里,它将始终从文件的开头传输。所以这条线需要
bytesTransferred += inChannel.transferTo(bytesTransferred , inChannel.size(), outChannel);
mavarazy在他的回答中提到他不确定在使用inChannel.size()
时是否需要循环,因为期望是如果你提供整个大小,它将复制整个文件。但是,如果输出通道的缓冲区具有较少的可用空间,则实际传输可能小于请求的字节数。所以你需要在他的第二个代码片段中使用循环。
答案 2 :(得分:0)
除非您有充分的理由使用Files.copy(Path, Path, CopyOption...)。