FileChannel.transferTo dla dużych plików w windows

Korzystanie z Javy NIO use może szybciej kopiować plik. Znalazłem dwa rodzaje metod głównie przez internet, aby wykonać tę pracę.

public static void copyFile(File sourceFile, File destinationFile) throws IOException {
    if (!destinationFile.exists()) {
        destinationFile.createNewFile();
    }

    FileChannel source = null;
    FileChannel destination = null;
    try {
        source = new FileInputStream(sourceFile).getChannel();
        destination = new FileOutputStream(destinationFile).getChannel();
        destination.transferFrom(source, 0, source.size());
    } finally {
        if (source != null) {
            source.close();
        }
        if (destination != null) {
            destination.close();
        }
    }
}

W 20 bardzo przydatnych fragmentów kodu Java dla programistów Java znalazłem inny komentarz i trick:

public static void fileCopy(File in, File out) throws IOException {
    FileChannel inChannel = new FileInputStream(in).getChannel();
    FileChannel outChannel = new FileOutputStream(out).getChannel();
    try {
        // inChannel.transferTo(0, inChannel.size(), outChannel); // original -- apparently has trouble copying large files on Windows
        // magic number for Windows, (64Mb - 32Kb)
        int maxCount = (64 * 1024 * 1024) - (32 * 1024);
        long size = inChannel.size();
        long position = 0;
        while (position < size) {
            position += inChannel.transferTo(position, maxCount, outChannel);
        }
    } finally {
        if (inChannel != null) {
            inChannel.close();
        }
        if (outChannel != null) {
            outChannel.close();
        }
    }
}

Ale nie znalazłem ani nie zrozumiałem co to znaczy

"magiczna liczba Dla Windows, (64Mb-32KB)"

Mówi, że inChannel.transferTo(0, inChannel.size(), outChannel) ma problem w windows, jest 32768 (= (64 * 1024 * 1024) - (32 * 1024)) bajt jest optymalny dla ta metoda.

Author: Tapas Bose, 2011-09-11

3 answers

System Windows ma twardy limit maksymalnego rozmiaru transferu, a jeśli go przekroczysz, otrzymasz wyjątek runtime. Więc musisz nastroić. Druga wersja, którą podasz, jest lepsza, ponieważ nie zakłada, że plik został przesłany w całości jednym wywołaniem transferTo(), co zgadza się z Javadoc.

Ustawienie rozmiaru transferu ponad 1MB i tak jest dość bezsensowne.

EDIT twoja druga wersja ma wadę. Należy zmniejszyć size o kwotę przekazaną za każdym razem. Informatyka powinno być bardziej jak:

while (position < size) {
    long count = inChannel.transferTo(position, size, outChannel);
    if (count > 0)
    {
        position += count;
        size-= count;
    }
}
 6
Author: user207421,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-07 08:24:13

Czytałem, że jest to dla kompatybilności z systemem operacyjnym Windows 2000.

Źródło: http://www.rgagnon.com/javadetails/java-0064.html

Cytat: w win2000, transferTo() nie przesyła Plików > 2^31-1 bajtów. rzuca wyjątek " java. io. IOException: brak wystarczających zasobów systemowych do ukończenia żądanej usługi jest wyrzucany."Obejściem jest kopiowanie w pętli 64Mb za każdym razem, dopóki nie ma więcej danych.

 0
Author: Danny Rancher,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-04 03:26:41

Wydaje się, że istnieją niepotwierdzone dowody na to, że próby przeniesienia więcej niż 64 MB na raz w niektórych wersjach systemu Windows skutkują powolną kopią. Stąd to sprawdzenie: wydaje się być wynikiem pewnych szczegółów podstawowego kodu natywnego, który implementuje operację transferTo w systemie Windows.

 -1
Author: Femi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-11 16:12:21