Вітання! Сьогодні ми поговоримо про роботу з файлуми та каталогами. Ти вже знаєш, як керувати вмістом файлів: у нас було чимало занять, присвячених цьому:) Думаю, ти легко зможеш згадати кілька класів, які потрібні для цих цілей. На сьогоднішній лекції ми поговоримо саме про управління файлуми — про створення, перейменування тощо. До появи Java 7 усі подібні операції проводабося за допомогою класу File. Про його роботу ти можеш прочитати тут . Але в Java 7 творці мови вирішабо змінити роботу з файлуми та каталогами. Це сталося через те, що клас Fileмав низку недоліків. Наприклад, у ньому не було методу copy(), який дозволив би скопіювати файл з одного місця в інше (начебто, явно необхідна функція). Крім того, у класіFileбуло досить багато методів, які повертали booleanзначення. При помилці такий метод повертає false , а чи не викидає виняток, що робить діагностику помилок і встановлення причин дуже непростим справою. Замість єдиного класу Fileз'явабося цілих 3 класи: Paths, Pathі Files. Ну а якщо бути точним, Pathце інтерфейс, а не клас. Давай розберемося, чим вони один від одного відрізняються і навіщо потрібний кожен із них. Почнемо з найлегшого - Paths.

Paths

Paths- Це дуже простий клас з єдиним статичним способом get(). Його створабо виключно для того, щоб з переданого рядка або URI отримати об'єкт типу Path. Іншої функціональності в нього немає. Ось приклад його роботи:
import java.nio.file.Path;
import java.nio.file.Paths;

public class Main {

   public static void main(String[] args) {

       Path testFilePath = Paths.get("C:\\Users\\Username\\Desktop\\testFile.txt");
   }
}
Чи не найскладніший клас, так? :) Ну, якщо ми вже отримали об'єкт типу Path, давай розбиратися, що це за Pathтакий і навіщо він потрібен :)

Path

Path, за великим рахунком, це перероблений аналог класу File. Працювати з ним значно простіше, ніж File. По-перше , з нього прибрали багато утилітних (статичних) методів, і перенесли їх у клас Files. По-друге , Pathбули впорядковані значення методів, що повертаються. У класі Fileметоди повертали то String, то boolean, то Fileрозібратися було непросто. Наприклад, був метод getParent(), який повертав батьківський шлях для поточного файлу у вигляді рядка. Але при цьому був метод getParentFile(), який повертав те саме, але у вигляді об'єкта File! Це явно надмірно. Тому в інтерфейсі Pathметод getParent()та інші методи роботи з файлуми повертають просто об'єкт.Path. Жодної купи варіантів - все легко і просто. Які ж корисні методи є у Path? Ось деякі з них та приклади їх роботи:
  • getFileName()- Повертає ім'я файлу з шляху;

  • getParent()— повертає «батьківську» директорію по відношенню до поточного шляху (тобто директорію, яка знаходиться вище по дереву каталогів);

  • getRoot()- Повертає «кореневу» директорію; тобто ту, що знаходиться на вершині дерева каталогів;

  • startsWith(), endsWith()- перевіряють, чи починається/закінчується шлях з переданого шляху:

    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    public class Main {
    
       public static void main(String[] args) {
    
           Path testFilePath = Paths.get("C:\\Users\\Username\\Desktop\\testFile.txt");
    
           Path fileName = testFilePath.getFileName();
           System.out.println(fileName);
    
           Path parent = testFilePath.getParent();
           System.out.println(parent);
    
           Path root = testFilePath.getRoot();
           System.out.println(root);
    
           boolean endWithTxt = testFilePath.endsWith("Desktop\\testFile.txt");
           System.out.println(endWithTxt);
    
           boolean startsWithLalala = testFilePath.startsWith("lalalala");
           System.out.println(startsWithLalala);
       }
    }

    Виведення в консоль:

    testFile.txt
    C:\Users\Username\Desktop
    C:\
    true
    false

    Зверніть увагу на те, як працює метод endsWith(). Він перевіряє, чи поточний шлях закінчується на переданий шлях . Саме на шлях , а не на набір символів .

    Порівняй результати цих двох викликів:

    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    public class Main {
    
       public static void main(String[] args) {
    
           Path testFilePath = Paths.get("C:\\Users\\Username\\Desktop\\testFile.txt");
    
           System.out.println(testFilePath.endsWith("estFile.txt"));
           System.out.println(testFilePath.endsWith("Desktop\\testFile.txt"));
       }
    }

    Виведення в консоль:

    false
    true

    У метод endsWith()потрібно передавати саме повноцінний шлях, а не просто набір символів: інакше результатом завжди буде false , навіть якщо поточний шлях дійсно закінчується такою послідовністю символів (як у випадку “estFile.txt” у прикладі вище).

    Крім того, є Pathгрупа методів, яка спрощує роботу з абсолютними (повними) та відносними шляхами .

Давай розглянемо ці методи:
  • boolean isAbsolute()- Повертає true , якщо поточний шлях є абсолютним:

    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    public class Main {
    
       public static void main(String[] args) {
    
           Path testFilePath = Paths.get("C:\\Users\\Username\\Desktop\\testFile.txt");
    
           System.out.println(testFilePath.isAbsolute());
       }
    }

    Виведення в консоль:

    true

  • Path normalize()— нормалізує поточний шлях, видаляючи з нього непотрібні елементи. Ти, можливо, знаєш, що у популярних операційних системах при позначенні шляхів часто використовуються символи “.” (“поточна директорія”) та “..” (батьківська директорія). Наприклад: " ./Pictures/dog.jpg " означає, що в тій директорії, в якій ми зараз знаходимося, є папка Pictures, а в ній - файл "dog.jpg"

    Так ось. Якщо у твоїй програмі з'явився шлях, який використовує “.” або “..”, метод normalize()дозволить видалити їх і отримати шлях, в якому вони не будуть:

    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    public class Main {
    
       public static void main(String[] args) {
    
    
           Path path5 = Paths.get("C:\\Users\\Java\\.\\examples");
    
           System.out.println(path5.normalize());
    
           Path path6 = Paths.get("C:\\Users\\Java\\..\\examples");
           System.out.println(path6.normalize());
       }
    }

    Виведення в консоль:

    C:\Users\Java\examples
    C:\Users\examples

  • Path relativize()- Обчислює відносний шлях між поточним і переданим шляхом.

    Наприклад:

    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    public class Main {
    
       public static void main(String[] args) {
    
           Path testFilePath1 = Paths.get("C:\\Users\\Users\\Users\\Users");
           Path testFilePath2 = Paths.get("C:\\Users\\Users\\Users\\Users\\Username\\Desktop\\testFile.txt");
    
           System.out.println(testFilePath1.relativize(testFilePath2));
       }
    }

    Виведення в консоль:

    Username\Desktop\testFile.txt

Повний перелік методів Pathдосить великий. Знайти їх все ти зможеш у документації Oracle . Ми ж перейдемо до розгляду Files.

Files

Files- Це утилітний клас, куди були винесені статичні методи класу File. Files— це приблизно те саме, що й Arraysабо Collectionsтільки працює він з файлуми, а не з масивами і колекціями :) Він зосереджений на керуванні файлуми і директоріями. Використовуючи статичні методи Files, ми можемо створювати, видаляти та переміщувати файли та директорії. Для цих операцій використовуються методи createFile()(для директорій - createDirectory()), move()і delete(). Ось як ними користуватися:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

public class Main {

   public static void main(String[] args) throws IOException {

       //Створення файлу
       Path