如何在Java

时间:2018-09-11 17:37:21

标签: java linux ubuntu-16.04 java-io

我正在编写程序部分,只是为了将文件从源复制到目标文件。该代码应该可以正常工作,但是如果目标文件达到4.3 GB大小,则如果文件很大,则复制过程将结束,例外。例外是“文件过大”,看起来像:

java.io.IOException: Die Datei ist zu groß
at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
at sun.nio.ch.FileDispatcherImpl.write(FileDispatcherImpl.java:60)
at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
at sun.nio.ch.IOUtil.write(IOUtil.java:65)
at sun.nio.ch.FileChannelImpl.write(FileChannelImpl.java:211)
at java.nio.channels.Channels.writeFullyImpl(Channels.java:78)
at java.nio.channels.Channels.writeFully(Channels.java:101)
at java.nio.channels.Channels.access$000(Channels.java:61)
at java.nio.channels.Channels$1.write(Channels.java:174)
at java.nio.file.Files.copy(Files.java:2909)
at java.nio.file.Files.copy(Files.java:3069)
at sample.Controller.copyStream(Controller.java:318)

产生方法如下:

    private void copyStream(File src, File dest){
    try {

        FileInputStream fis = new FileInputStream(src);
        OutputStream newFos = java.nio.file.Files.newOutputStream(dest.toPath(),StandardOpenOption.WRITE);

        Files.copy(src.toPath(),newFos);

        newFos.flush();
        newFos.close();
        fis.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

我还尝试使用java.io Fileoutputstream并以KB方式进行写入,但是发生了相同的情况。如何复制或创建大于4.3 GB的文件?除了Java以外,还有其他语言可能吗?我在Linux(Ubuntu LTS 16.04)上运行此程序。

谢谢。


编辑:

非常感谢大家的帮助。如您所说,文件系统就是问题所在。在我格式化文件系统以使其正常运行之后。

1 个答案:

答案 0 :(得分:6)

允许POSIX(以及Unix)系统在路径(从File.getPath()或路径的组成部分(从File.getName()获得的最后一个内容)上施加最大长度)。由于文件名太长,您可能会遇到此问题。

在这种情况下,文件open的操作系统调用将失败,并返回ENAMETOOLONG error code

但是,“文件太大”消息通常与“ EFBIG”错误代码相关联。这更可能是由write系统调用导致的:

  

尝试写入的文件超出了实现相关的最大文件大小或进程的文件大小限制。

也许正在打开文件以进行追加,并且文件末尾隐含的lseek给出了EFBIG错误。

最后,如果必须对RAM进行某些操作,则可以尝试其他复制方法。

另一个选择是磁盘已满。

要复制文件,基本上有四种方法[事实证明,在基本级别上,流是最快的]:

使用流复制:

private static void copyFileUsingStream(File source, File dest) throws IOException {
    InputStream is = null;
    OutputStream os = null;
    try {
        is = new FileInputStream(source);
        os = new FileOutputStream(dest);
        byte[] buffer = new byte[1024];
        int length;
        while ((length = is.read(buffer)) > 0) {
            os.write(buffer, 0, length);
        }
    } finally {
      is.close();
      os.close();
    }
}

使用Java NIO类进行复制:

private static void copyFileUsingChannel(File source, File dest) throws IOException {
    FileChannel sourceChannel = null;
    FileChannel destChannel = null;
    try {
        sourceChannel = new FileInputStream(source).getChannel();
        destChannel = new FileOutputStream(dest).getChannel();
        destChannel.transferFrom(sourceChannel, 0, sourceChannel.size());
    }finally{
           sourceChannel.close();
           destChannel.close();
    }
}

使用Apache Commons IO FileUtils复制:

private static void copyFileUsingApacheCommonsIO(File source, File dest) throws IOException {
    FileUtils.copyFile(source, dest);
}

以及使用Java 7和Files类的方法:

private static void copyFileUsingJava7Files(File source, File dest) throws IOException {
    Files.copy(source.toPath(), dest.toPath());
}

编辑1 : 如评论中所建议,这是三个SO问题,它们涵盖了问题并解释了四种更好的复制方法:

感谢@jww指出