java:使用 nio 复制时创建的损坏的 zip 文件
java : corrupted zip file created when copy using nio
我已经实现了以下代码来复制文件(二进制文件)
代码
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 文件大约 9GB。
试试这个:
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)
transferTo
方法的第一个参数给出传输的起始位置,不是相对于流停止的位置,而是相对于文件的开头。因为你把 0
放在那里,所以它总是从文件的开头开始传输。所以该行需要
bytesTransferred += inChannel.transferTo(bytesTransferred , inChannel.size(), outChannel);
mavarazy 在他的回答中提到,他不确定在使用 inChannel.size()
时是否需要循环,因为预期是如果您提供整个大小,它将复制整个文件。但是,如果输出通道的缓冲区可用空间较少,实际传输可能会少于请求的字节数。所以你确实需要他的第二个代码片段中的循环。
除非你有充分的理由最好使用 Files.copy(Path, Path, CopyOption...)。
我已经实现了以下代码来复制文件(二进制文件) 代码
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 文件大约 9GB。
试试这个:
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)
transferTo
方法的第一个参数给出传输的起始位置,不是相对于流停止的位置,而是相对于文件的开头。因为你把 0
放在那里,所以它总是从文件的开头开始传输。所以该行需要
bytesTransferred += inChannel.transferTo(bytesTransferred , inChannel.size(), outChannel);
mavarazy 在他的回答中提到,他不确定在使用 inChannel.size()
时是否需要循环,因为预期是如果您提供整个大小,它将复制整个文件。但是,如果输出通道的缓冲区可用空间较少,实际传输可能会少于请求的字节数。所以你确实需要他的第二个代码片段中的循环。
除非你有充分的理由最好使用 Files.copy(Path, Path, CopyOption...)。