Как копировать файлы размером более 4,3 ГБ в Java - PullRequest
0 голосов
/ 11 сентября 2018

Я пишу программную часть просто для копирования файла из исходного файла в целевой.Код работает так же, как и должен, но если файл большого размера, процесс копирования завершится, когда размер файла назначения достигнет 4,3 ГБ, за исключением.Исключением является «файл слишком велик», он выглядит следующим образом:

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 ипишите в килобайтах, но там бывает то же самое.Как я могу копировать или создавать файлы размером более 4,3 ГБ?Возможно ли это на другом языке, кроме Java?Эту программу я запускаю на Linux (Ubuntu LTS 16.04).

Заранее спасибо.


Редактировать:

Большое спасибо всем вам за помощь.Как вы сказали, проблема была в файловой системе.После того, как я отформатировал файловую систему для exfat, она работает нормально.

1 Ответ

0 голосов
/ 11 сентября 2018

POSIX (и, следовательно, Unix) системам разрешено устанавливать максимальную длину пути (то, что вы получаете от File.getPath() или компонентов пути (последний из которых вы можете получить с File.getName()). Вы можете Эта проблема возникает из-за длинного имени файла.

В этом случае системный вызов файла open завершится с ошибкой ENAMETOOLONG с кодом ошибки .

Однако сообщение «Файл слишком большой» обычно связано с кодом ошибки «EFBIG». Это более вероятно в результате системного вызова write:

Была предпринята попытка записать файл, размер которого превышает зависящий от реализации максимальный размер файла или ограничение размера файла процесса.

Возможно, файл открывается для добавления, и подразумеваемое значение lseek в конце файла приводит к ошибке EFBIG.

В конце концов, вы можете попробовать другие способы копирования, если это связано с вашей оперативной памятью.

Также другой вариант может быть, что диск заполнен.

Для копирования файлов существует в основном четыре способа [и оказывается, что потоки - самый быстрый на базовом уровне]:

Копирование с потоками:

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 за указание на это

...