简体   繁体   English

java:使用nio复制时创建的损坏的zip文件

[英]java : corrupted zip file created when copy using nio

I have implement following code to copy file(binary file) code 我已经实现了以下代码来复制文件(二进制文件)的代码

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);
            }
        }

    }

I have test code with one zip file. 我有一个zip文件的测试代码。 when i verify file I found that file which generated is corrupt(size was increased). 当我验证文件时,我发现生成的文件已损坏(大小已增加)。 Source zip file is about 9GB. 源zip文件约为9GB。

Try this: 尝试这个:

  while(bytesTransferred < inChannel.size()){
      bytesTransferred += inChannel.transferTo(bytesTransferred, inChannel.size() - bytesTransferred, outChannel);
  }

Also, I would refer to IOUtils implementation, as a reference 另外,我将参考IOUtils的实现,作为参考

https://github.com/apache/commons-io/blob/master/src/main/java/org/apache/commons/io/FileUtils.java https://github.com/apache/commons-io/blob/master/src/main/java/org/apache/commons/io/FileUtils.java

specifically 特别

private static void doCopyFile(final File srcFile, final File destFile, final boolean preserveFileDate)

The transferTo method's first argument gives the position from which to transfer, not relative to where the stream left off, but relative to the start of the file. transferTo方法的第一个参数提供了要从其传输的位置,而不是相对于流离开的位置,而是相对于文件的开始。 Since you put 0 there it will always transfer from the start of the file. 由于您在此处放置0 ,因此它将始终从文件开头开始传输。 So that line needs to be 所以那条线需要

bytesTransferred += inChannel.transferTo(bytesTransferred , inChannel.size(), outChannel);

mavarazy mentioned in his answer he's not sure if you need a loop when using inChannel.size() , since the expectation is that if you supply the whole size it will copy the entire file. mavarazy在他的回答中提到,他不确定使用inChannel.size()时是否需要循环,因为期望的是,如果您提供整个大小,它将复制整个文件。 However, the actual transfer might be less than the requested number of bytes if the output channel's buffer has less room available. 但是,如果输出通道的缓冲区的可用空间较少,则实际传输可能会少于请求的字节数。 So you do need the loop as in his second code snippet. 因此,您确实需要像他的第二个代码片段中那样的循环。

除非您有充分的理由,否则最好使用Files.copy(Path,Path,CopyOption ...)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM