JavaRush /Курси /Java Syntax Zero /Робота з файлами в Java

Робота з файлами в Java

Java Syntax Zero
Рівень 16 , Лекція 6
Відкрита

1. Клас Files

Клас Files

Щоб працювати з файлами, є шикарний утилітний клас — java.nio.file.Files. У нього є методи просто на всі випадки життя. Всі методи цього класу статичні і працюють з об'єктами типу Path. Методів дуже багато, тому ми розглянемо тільки основні:

Метод Опис
Path createFile(Path path)
Створює новий файл за шляхом path
Path createDirectory(Path path)
Створює нову директорію
Path createDirectories(Path path)
Створює кілька директорій
Path createTempFile(prefix, suffix)
Створює тимчасовий файл
Path createTempDirectory(prefix)
Створює тимчасову директорію
void delete(Path path)
Видаляє файл або директорію, якщо вона порожня
Path copy(Path src, Path dest)
Копіює файл
Path move(Path src, Path dest)
Переміщує файл
boolean isDirectory(Path path)
Перевіряє, що шлях — це директорія, а не файл
boolean isRegularFile(Path path)
Перевіряє, що шлях — це файл, а не директорія
boolean exists(Path path)
Перевіряє, що об'єкт за заданим шляхом існує
long size(Path path)
Повертає розмір файлу
byte[] readAllBytes(Path path)
Повертає весь вміст файлу у вигляді масиву байт
String readString(Path path)
Повертає весь вміст файлу у вигляді рядка
List<String> readAllLines(Path path)
Повертає весь вміст файлу у вигляді списку рядків
Path write(Path path, byte[])
Записує у файл масив байт
Path writeString(Path path, String str)
Записує у файл рядок
DirectoryStream<Path> newDirectoryStream(Path dir)
Повертає колекцію файлів (та піддиректорій) із заданої директорії

2. Створення файлів та директорій

Файли та директорії створювати дуже просто. Переконаємося на прикладах:

Код Примітка
Files.createFile(Path.of("c:\\readme.txt"));
Створює файл
Files.createDirectory(Path.of("c:\\test"));
Створює директорію
Files.createDirectories(Path.of("c:\\test\\1\\2\\3"));
Створює директорію і всі потрібні піддиректорії, якщо їх не існує.

3. Копіювання, переміщення та видалення

Копіювати, переміщати та видаляти файли так само легко. На директорії це теж розповсюджується, але вони повинні бути порожні.

Код Примітка
Path path1 = Path.of("c:\\readme.txt");
Path path2 = Path.of("c:\\readme-copy.txt");
Files.copy(path1, path2);
Копіює файл
Path path1 = Path.of("c:\\readme.txt");
Path path2 = Path.of("d:\\readme-new.txt");
Files.move(path1, path2);
Переміщує та перейменовує файл
Path path = Path.of("d:\\readme-new.txt");
Files.delete(path);
Видаляє файл

4. Перевірка типу файлу та факту існування

Коли у тебе є якийсь шлях, отриманий ззовні, ти, ймовірно, захочеш знати, це файл чи директорія. Ну і загалом: існує такий файл/директорія чи ні?

Для цього теж є спеціальні методи. Також можна легко дізнатися довжину файлу:

Код Примітка
Files.isRegularFile(Path.of("c:\\readme.txt"));
true
Files.isDirectory(Path.of("c:\\test"));
true
 Files.exists(Path.of("c:\\test\\1\\2\\3"));
false
Files.size(Path.of("c:\\readme.txt"));
10112

5. Робота з вмістом файлу

І нарешті, є ціла серія методів, які дозволяють легко прочитати або записати вміст файлу. Приклад:

Код Опис
Path path = Path.of("c:\\readme.txt");
List<String> list = Files.readAllLines(path);

for (String str : list)
   System.out.println(str);

Читаємо вміст файлу у вигляді списку рядків.

Виводимо рядки на екран


6. Отримання вмісту директорії

Залишився ще найцікавіший метод — отримання файлів і піддиректорій у заданій директорії.

Для цього є спеціальний метод — newDirectoryStream(), який повертає спеціальний об'єкт типу DirectoryStream<Path>. У нього є ітератор(!), і за допомогою цього ітератора можна отримати всі файли та піддиректорії заданої директорії.

Виглядає простіше, ніж здається:

Код Опис
Path path = Path.of("c:\\windows");

try (DirectoryStream<Path> files = Files.newDirectoryStream(path)) {
   for (Path path : files)
      System.out.println(path);
}


Отримуємо об'єкт зі списком файлів
Цикл за списком файлів

Об'єкт DirectoryStream<Path> має дві властивості. По-перше, у нього є ітератор, який повертає шляхи до файлів, і ми можемо цей об'єкт використовувати всередині циклу for-each.

А по-друге, цей об'єкт є потоком даних, і його потрібно закривати за допомогою методу close(), ну або використовувати всередині try-with-resources.



7. Метод Files.newInputStream

Починаючи з Java 5 класи FileInputStream і FileOutputStream стали вважатися застарілими. Одним із їх мінусів було те, що при створенні об'єкта цих класів одразу відбувається створення файлів на диску. І потенційно викидаються всі помилки, пов'язані зі створенням файлів.

Згодом це було визнано не найкращим рішенням. Тому для створення об'єктів-файлів рекомендується використовувати методи утилітного класу – java.nio.Files.

Ось порівняння старого підходу до створення файлів і нового:

Було
String src = "c:\\projects\\log.txt";
InputStream input = new FileInputStream( src );
Стало
String src = "c:\\projects\\log.txt";
InputStream input = Files.newInputStream( Path.of( src ) );

Аналогічно заміна і для FileOutputStream:

Було
String src = "c:\\projects\\log.txt";
OutputStream  output = new FileOutputStream( src );
Стало
String src = "c:\\projects\\log.txt";
OutputStream  output = Files.newOutputStream( Path.of( src ) );

Коментарі (19)
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ
Андрій Рівень 18
25 квітня 2024
В мене таке відчуття, ніби коли написали 16 рівень, то викликали для нього reverse()
Olexandr Рівень 47
21 січня 2024
Хороші задачі. В лекції нічого не забуто, як тут пишуть. Просто знов таки логіка. Я, наприклад, здогадувався що з таргет папкою щось не так просто, але що... Я так розумію, resolve використали, тому що при перевірці вводиться неповний шлях до папки. Треба було здогадатися зробити перевірку на абсолютний шлях, і якщо його нема - тоді і застосувати resolve. Але якусь підказочку про абсолютність шляху могли б і лишити, ми ж все ж таки не комерційний проект пишемо поки що, і коли в тебе не працює і абсолютно неясно чому - таке собі..... ps згоден, що з Files.newInputStream - загнали..... Спочатку рівня гризли задачі абсолютно без підготовки, гуглили як могли. В кінці рівня дали цю теорію але без задач. Супер, чо....
Aleksey Golovin Рівень 55
29 вересня 2025
resolve робе шлях до файлу призначення. Наприклад у нас є C:\\FirsFolder\ та C:\\SecondFolder\ У першій папці ми знайшли файл C:\\FirsFolder\test.txt Нам треба створити посилання на місце переміщення, а саме C:\\SecondFolder\test.txt Тобто нам треба взяти вказівник на другу папки та поєднати його з назвою файла. Назву файла ми отримаємо за допомогою методу getFileName() до вказівника на наш файл. А поєднуємо вказівник на директорію та назву файлу за допомогою resolve()
Andriy Рівень 26
24 червня 2023
Хочу ще раз щиро порекомендувати chatGPT. Після декількох спроб розв'язати задачу 4 я зміг за допомогою дебагу знайти проблему і вручну конкатуванням створював новий шлях. Хоча на моїй машині в моєму конкретному випадку це працювало, валідацію не проходило. Швидше за все через відмінність в будові шляху в різних ОС. Після цього я закинув свій код в chatGPT і попросив оптимізувати створення шляху. Він зразу і запровонував мені resolve, пояснивши деталі

In this updated code, the xxx.resolve(yyy) expression resolves the yyy path against the xxx, creating the newPath directly.

This approach is cleaner and more reliable than manually concatenating strings and handling path separators yourself.
Зразу після цього виправлення задача пройшла валідацію. Також я закидав chatGPT питаннями про resolve, на які він дав відповіді з прикладами, що допомогло зрозуміти принцип роботи resolve загалом
Pavlo Kezin Рівень 23
23 вересня 2023
тільки чат іноді вирішує задачу взагалі за тебе.
Olexandr Рівень 47
23 січня 2024
колись закінчиться тим, що цей чат і на роботу приймуть за тебе...
Oleksandr Tkachenko Рівень 51
22 квітня 2023
тут хтось писав що ресурси мають бути закриті) де в вашому рішені закритя сканера?)
Yevhenii Рівень 17
7 квітня 2023
Тільки зараз нам вирішили розповісти про метод List<String> readAllLines(Path path)? А завдання з використанням цього методу було три лекції тому : просто шикарно(
WhoAMI Рівень 51
23 листопада 2022
а як у передостанній задачі реалізувати щоб копіювало і файли які знаходились в директоріях, при цьому не копіювавши самі директорії (тобто усі файли які містяться у поточній та вкладеній директоріях копіюються у таргет директорію самі файли без директорій).
Anonymous #696530 Рівень 19
8 листопада 2022
Дві останні задачі один в один...
Sava_crosava Рівень 23
25 жовтня 2023
це для набиття руки)
FAUST_ua Рівень 29
11 вересня 2022
Дивна задача "Поверхневе копіювання": 1) де в лекції розказували про resolve ? 2) при вашому варіанті вирішення (який рахується правильним еталоном) програма не спрацювала та видала такі помилки: Exception in thread "main" java.nio.file.NoSuchFileException: <SOURSE FILE> -> <TARGET FILE> at java.base/sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:85) at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:103) at java.base/sun.nio.fs.WindowsFileCopy.copy(WindowsFileCopy.java:209) at java.base/sun.nio.fs.WindowsFileSystemProvider.copy(WindowsFileSystemProvider.java:284) at java.base/java.nio.file.Files.copy(Files.java:1305) at ua.javarush.task.pro.task15.task1519.Solution.main(Solution.java:22) Така помилка виникає коли <TARGET DIRECTORY> не існує.
Bandiu Band Рівень 25
23 вересня 2022
Про resolve в лекціях було, в описі методу copy ніхто не уточнив що цілевий шлях має містити не лише шлях до папки, а має включати ще й назву самого фалу (вже в новій директорії). Як приклад: Pach pach1 = Pach.of("c:\1\doc.txt"); Pach pach2 = Pach.of("c:\2\doc.txt"); Files.copy(path1,path2); Для цього і потрібен resolve(), якщо з ним то буде якось так. Pach pach1 = Pach.of("c:\1\doc.txt"); Pach pach2 = Pach.of("c:\2"); Path resolve = pach2.resolve(path1.getFileName()); Files.copy(path1,resolve);
Artem Рівень 30
1 вересня 2022
так багато інфи за resolve...
Niko Рівень 36
30 липня 2022
В двух последних без resolve не засчитывает. Хоть можно у так Path file = Path.of(targetDirectory+"\\"+Path.of(String.valueOf(path)).getFileName()); К директории