【问题标题】:java : corrupted zip file created when copy using niojava:使用 nio 复制时创建的损坏的 zip 文件
【发布时间】:2017-10-19 11:30:46
【问题描述】:

我已经实现了以下代码来复制文件(二进制文件) 代码

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。

【问题讨论】:

    标签: java io nio


    【解决方案1】:

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

    【讨论】:

    • Files.copy 使用我已经实现的读/写机制进行复制,其中存在性能问题。
    【解决方案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)
    

    【讨论】:

      【解决方案3】:

      transferTo 方法的第一个参数给出了传输的位置,不是相对于流停止的位置,而是相对于文件的开头。由于您将0 放在那里,它将始终从文件的开头传输。所以这条线需要是

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

      mavarazy 在他的回答中提到,他不确定在使用inChannel.size() 时是否需要循环,因为期望如果您提供整个大小,它将复制整个文件。但是,如果输出通道的缓冲区可用空间较少,则实际传输可能少于请求的字节数。所以你确实需要他的第二个代码 sn-p 中的循环。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-09
        相关资源
        最近更新 更多