如何在java中复制大于4.3 GB的文件

时间:2021-06-08 21:45:46

I'm writing a program part simply to copy a file from source to a destination File. The code works as well it should but if there is a file large file the process of copy will end up, after the destination file reach a size of 4.3 GB, with an exception. The exception is a "file is to large" it looks like:

我正在编写一个程序部分,只是为了将文件从源文件复制到目标文件。代码也可以正常运行,但是如果存在文件大文件,则在目标文件达到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)

The method to produce that is following:

产生的方法如下:

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

I also tried to use java.io Fileoutputstream and write in a kbyte way, but there happends the same. How can I copy or create files larger than 4.3 GB? Is it maybe possible in other language than java? This programm I run on a Linux (Ubuntu LTS 16.04).

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

Thanks in advance.

提前致谢。


Edit:

Thanks very much you all for your help. As you said, the file system was the problem. After i formated the file system to exfat it works fine.

非常感谢大家的帮助。正如你所说,文件系统是问题所在。在我将文件系统格式化为exfat后,它工作正常。

1 个解决方案

#1


6  

POSIX (and thus Unix) systems are allowed to impose a maximum length on the path (what you get from File.getPath() or the components of a path (the last of which you can get with File.getName()). You might be seeing this problem because of the long name for the file.

允许POSIX(以及Unix)系统在路径上施加最大长度(从File.getPath()获取的内容或路径的组件(使用File.getName()可以获得最后一个)。可能是因为文件的长名称而看到此问题。

In that case, the file open operating system call will fail with an ENAMETOOLONG error code.

在这种情况下,文件打开操作系统调用将失败,并显示ENAMETOOLONG错误代码。

However, the message "File too large" is typically associated with the ´EFBIG´ error code. That is more likely to result from a write system call:

但是,消息“文件太大”通常与'EBBIG'错误代码相关联。这更可能是由写系统调用引起的:

An attempt was made to write a file that exceeds the implementation-dependent maximum file size or the process' file size limit.

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

Perhaps the file is being opened for appending, and the implied lseek to the end of the file is giving the EFBIG error.

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

In the end, you could try other methods of copying if it has to do something with your RAM.

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

Also another option could be that the disk is full.

另一种选择可能是磁盘已满。

To copy files there are basically four ways [and it turns out streams is the fastest on a basic level] :

复制文件基本上有四种方式[并且结果是基本级别的流是最快的]:

Copy with streams:

使用流复制:

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

Copy with Java NIO classes:

使用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();
    }
}

Copy with Apache Commons IO FileUtils:

使用Apache Commons IO FileUtils进行复制:

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

and your Method by using Java 7 and the Files class:

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

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

Edit 1: as suggested in the comments, here are three SO-questions, which cover the problem and explain the four different methodes of copying better:

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

Thanks to @jww for pointing it out

感谢@jww指出它

#1


6  

POSIX (and thus Unix) systems are allowed to impose a maximum length on the path (what you get from File.getPath() or the components of a path (the last of which you can get with File.getName()). You might be seeing this problem because of the long name for the file.

允许POSIX(以及Unix)系统在路径上施加最大长度(从File.getPath()获取的内容或路径的组件(使用File.getName()可以获得最后一个)。可能是因为文件的长名称而看到此问题。

In that case, the file open operating system call will fail with an ENAMETOOLONG error code.

在这种情况下,文件打开操作系统调用将失败,并显示ENAMETOOLONG错误代码。

However, the message "File too large" is typically associated with the ´EFBIG´ error code. That is more likely to result from a write system call:

但是,消息“文件太大”通常与'EBBIG'错误代码相关联。这更可能是由写系统调用引起的:

An attempt was made to write a file that exceeds the implementation-dependent maximum file size or the process' file size limit.

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

Perhaps the file is being opened for appending, and the implied lseek to the end of the file is giving the EFBIG error.

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

In the end, you could try other methods of copying if it has to do something with your RAM.

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

Also another option could be that the disk is full.

另一种选择可能是磁盘已满。

To copy files there are basically four ways [and it turns out streams is the fastest on a basic level] :

复制文件基本上有四种方式[并且结果是基本级别的流是最快的]:

Copy with streams:

使用流复制:

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

Copy with Java NIO classes:

使用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();
    }
}

Copy with Apache Commons IO FileUtils:

使用Apache Commons IO FileUtils进行复制:

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

and your Method by using Java 7 and the Files class:

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

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

Edit 1: as suggested in the comments, here are three SO-questions, which cover the problem and explain the four different methodes of copying better:

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

Thanks to @jww for pointing it out

感谢@jww指出它