Zawsze niepokoiło mnie, że jedynym sposobem na skopiowanie pliku w Javie jest otwarcie strumieni, zadeklarowanie bufora, odczytanie jednego pliku, zapętlenie go i zapisanie go w innej parze. Sieć jest zaśmiecona podobnymi, ale wciąż nieco różnymi implementacjami tego typu rozwiązania.
Czy istnieje lepszy sposób, który mieści się w granicach języka Java (co oznacza, że nie wymaga wykonywania poleceń specyficznych dla systemu operacyjnego)? Być może w jakimś niezawodnym pakiecie narzędziowym typu open source, który przynajmniej zasłoniłby tę podstawową implementację i zapewniłby rozwiązanie jednowierszowe?
Odpowiedzi:
Jak wspomniano powyżej, zestaw narzędzi Apache Commons IO jest najlepszym rozwiązaniem, w szczególności FileUtils . copyFile () ; poradzi sobie z każdym ciężkim podnoszeniem.
I jako postscript zauważ, że najnowsze wersje FileUtils (takie jak wydanie 2.0.1) dodały użycie NIO do kopiowania plików; NIO może znacznie zwiększyć wydajność kopiowania plików , w dużej mierze, ponieważ procedury NIO odraczają kopiowanie bezpośrednio do systemu operacyjnego / plików zamiast obsługiwać je poprzez odczytywanie i zapisywanie bajtów przez warstwę Java. Więc jeśli szukasz wydajności, warto sprawdzić, czy korzystasz z najnowszej wersji FileUtils.
źródło
Unikałbym używania mega api, takich jak apache commons. Jest to operacja uproszczona i jest wbudowana w JDK w nowym pakiecie NIO. W pewnym sensie było to już związane z poprzednią odpowiedzią, ale kluczową metodą w interfejsie NIO są nowe funkcje „transferTo” i „transferFrom”.
http://java.sun.com/javase/6/docs/api/java/nio/channels/FileChannel.html#transferTo(long,%20long,%20java.nio.channels.WritableByteChannel)
Jeden z powiązanych artykułów pokazuje świetny sposób na zintegrowanie tej funkcji z Twoim kodem za pomocą metody transferFrom:
Nauka NIO może być trochę trudna, więc możesz zaufać tej mechanice, zanim pójdziesz i spróbujesz nauczyć się NIO przez noc. Z własnego doświadczenia bardzo trudno jest się nauczyć, jeśli nie masz doświadczenia i zostałeś wprowadzony do IO za pośrednictwem strumieni java.io.
źródło
Teraz w Javie 7 możesz użyć następującej składni try-with-resource:
Lub jeszcze lepiej, można to również osiągnąć za pomocą nowej klasy Files wprowadzonej w Javie 7:
Dość sprytny, co?
źródło
Klasa użyteczności
Kopiowanie katalogu lub pliku
Przenoszenie katalogu lub pliku
Kopiowanie katalogu lub pliku rekurencyjnie
źródło
W Javie 7 jest to łatwe ...
źródło
Aby skopiować plik i zapisać go na docelowej ścieżce, możesz użyć poniższej metody.
źródło
Zauważ, że wszystkie te mechanizmy kopiują tylko zawartość pliku, a nie metadane, takie jak uprawnienia. Więc jeśli miałbyś skopiować lub przenieść plik wykonywalny .sh na Linuksie, nowy plik nie byłby wykonywalny.
Aby naprawdę skopiować lub przenieść plik, tj. Aby uzyskać taki sam wynik jak kopiowanie z wiersza poleceń, w rzeczywistości musisz użyć rodzimego narzędzia. Albo skrypt powłoki, albo JNI.
Najwyraźniej można to naprawić w java 7 - http://today.java.net/pub/a/today/2008/07/03/jsr-203-new-file-apis.html . Skrzyżowane palce!
źródło
Biblioteka Google Guava ma również metodę kopiowania :
Ostrzeżenie: jeśli
to
reprezentuje istniejący plik, plik ten zostanie zastąpiony zawartościąfrom
. Jeślito
ifrom
odnoszą się do tego samego pliku, zawartość tego pliku zostanie usunięta.Parametry:
from
- plik źródłowyto
- plik docelowyZgłasza:
IOException
- jeśli wystąpi błąd we / wyIllegalArgumentException
- jeślifrom.equals(to)
źródło
Dostępny standardowo w Javie 7, path.copyTo: http://openjdk.java.net/projects/nio/javadoc/java/nio/file/Path.html http://java.sun.com/docs/books/ tutorial / essential / io / copy.html
Nie mogę uwierzyć, że tyle czasu zajęło im ujednolicenie czegoś tak powszechnego i prostego, jak kopiowanie plików :(
źródło
Trzy możliwe problemy z powyższym kodem:
To dlatego
org.apache.tools.ant.util.ResourceUtils.copyResource
jest takie skomplikowane. Zauważ też, że chociaż transferFrom jest w porządku, transferTo psuje się w JDK 1.4 w Linuksie (patrz Bug ID: 5056395 ) - Jesse Glick Janźródło
Jeśli korzystasz z aplikacji internetowej, która już korzysta z Spring i nie chcesz dołączać Apache Commons IO do prostego kopiowania plików, możesz użyć FileCopyUtils z Spring.
źródło
Oto trzy sposoby łatwego kopiowania plików za pomocą jednego wiersza kodu!
Java7 :
java.nio.file.Files # copy
Appache Commons IO :
FileUtils # copyFile
Guawa :
Pliki # kopiuj
źródło
Files.copy
użycie tylko 2 parametrów jestPath
doStream
. Wystarczy dodać parametrStandardCopyOption.COPY_ATTRIBUTES
lubStandardCopyOption.REPLACE_EXISTING
doPath
celuPath
źródło
Według mojego testu kopia NIO z buforem jest najszybsza. Zobacz działający kod poniżej z mojego projektu testowego na https://github.com/mhisoft/fastcopy
}
źródło
Szybko i współpracuj ze wszystkimi wersjami Java, także Android:
źródło
Trochę za późno na imprezę, ale tutaj jest porównanie czasu kopiowania pliku przy użyciu różnych metod kopiowania plików. Zapętlałem metody 10 razy i brałem średnią. Najgorszym kandydatem wydaje się transfer plików przy użyciu strumieni IO:
Oto metody:
Jedyną wadą, jaką widzę podczas korzystania z klasy kanału NIO, jest to, że nadal nie mogę znaleźć sposobu na pokazanie postępu kopiowania plików pośrednich.
źródło