简体   繁体   中英

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. when i verify file I found that file which generated is corrupt(size was increased). Source zip file is about 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

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. Since you put 0 there it will always transfer from the start of the file. 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. 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 ...)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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