1. Общ преглед
В тази статия ще разгледаме често срещаните начини за копиране на файлове в Java.
Първо ще използваме стандартните API за IO и NIO.2 и две външни библиотеки: commons-io и guava.
2. IO API (преди JDK7)
На първо място, за да копираме файл с API на java.io , от нас се изисква да отворим поток, да преминем през съдържанието и да го запишем в друг поток:
@Test public void givenIoAPI_whenCopied_thenCopyExistsWithSameContents() throws IOException { File copied = new File("src/test/resources/copiedWithIo.txt"); try ( InputStream in = new BufferedInputStream( new FileInputStream(original)); OutputStream out = new BufferedOutputStream( new FileOutputStream(copied))) { byte[] buffer = new byte[1024]; int lengthRead; while ((lengthRead = in.read(buffer)) > 0) { out.write(buffer, 0, lengthRead); out.flush(); } } assertThat(copied).exists(); assertThat(Files.readAllLines(original.toPath()) .equals(Files.readAllLines(copied.toPath()))); }
Доста работа за внедряване на такава основна функционалност.
За наш късмет Java подобри основните си API и имаме по-опростен начин за копиране на файлове, използвайки NIO.2 API .
3. NIO.2 API (JDK7)
Използването на NIO.2 може значително да увеличи производителността на копиране на файлове, тъй като NIO.2 използва точки за вход на системата от по-ниско ниво.
Нека да разгледаме по-отблизо как файловете. методът copy () работи.
Методът copy () ни дава възможност да зададем незадължителен аргумент, представляващ опция за копиране. По подразбиране копирането на файлове и директории няма да замени съществуващите, нито ще копира файлови атрибути.
Това поведение може да се промени, като се използват следните опции за копиране:
- REPLACE_EXISTING - заменете файл, ако той съществува
- COPY_ATTRIBUTES - копиране на метаданни в новия файл
- NOFOLLOW_LINKS - не трябва да следва символични връзки
Класът NIO.2 Files предоставя набор от претоварени методи copy () за копиране на файлове и директории във файловата система.
Нека да разгледаме пример, използвайки copy () с два аргумента Path :
@Test public void givenNIO2_whenCopied_thenCopyExistsWithSameContents() throws IOException { Path copied = Paths.get("src/test/resources/copiedWithNio.txt"); Path originalPath = original.toPath(); Files.copy(originalPath, copied, StandardCopyOption.REPLACE_EXISTING); assertThat(copied).exists(); assertThat(Files.readAllLines(originalPath) .equals(Files.readAllLines(copied))); }
Имайте предвид, че копията на директории са плитки , което означава, че файловете и поддиректориите в директорията не се копират.
4. Apache Commons IO
Друг често срещан начин за копиране на файл с Java е използването на библиотеката commons-io .
Първо, трябва да добавим зависимостта:
commons-io commons-io 2.6
Последната версия може да бъде изтеглена от Maven Central.
След това, за да копираме файл, просто трябва да използваме метода copyFile () , дефиниран в класа FileUtils . Методът взема източник и целеви файл.
Нека да разгледаме JUnit тест, използвайки метода copyFile () :
@Test public void givenCommonsIoAPI_whenCopied_thenCopyExistsWithSameContents() throws IOException { File copied = new File( "src/test/resources/copiedWithApacheCommons.txt"); FileUtils.copyFile(original, copied); assertThat(copied).exists(); assertThat(Files.readAllLines(original.toPath()) .equals(Files.readAllLines(copied.toPath()))); }
5. Гуава
Накрая ще разгледаме библиотеката на Гуава на Google.
Отново, ако искаме да използваме Guava , трябва да включим зависимостта:
com.google.guava guava 23.0
Най-новата версия може да бъде намерена на Maven Central.
И ето начинът на Guava за копиране на файл:
@Test public void givenGuava_whenCopied_thenCopyExistsWithSameContents() throws IOException { File copied = new File("src/test/resources/copiedWithGuava.txt"); com.google.common.io.Files.copy(original, copied); assertThat(copied).exists(); assertThat(Files.readAllLines(original.toPath()) .equals(Files.readAllLines(copied.toPath()))); }
6. Заключение
В тази статия разгледахме най-често срещаните начини за копиране на файл в Java.
Пълното изпълнение на тази статия може да бъде намерено в Github.