Статьи

Полный курс по языку Java — от установки JDK до многопоточности и HTTP-запросов

Файлы и каталоги

Страница 23 из 30 · 2026-10-25 · 5 мин чтения

Path и Files

Современный API находится в пакете java.nio.file. Класс Path описывает путь, класс Files выполняет операции.

import java.nio.file.Path;public class PathDemo {    public static void main(String[] args) {        Path path = Path.of("data", "notes", "todo.txt");        System.out.println(path);        System.out.println(path.getFileName());        System.out.println(path.getParent());        System.out.println(path.isAbsolute());        System.out.println(path.toAbsolutePath());        System.out.println(path.resolveSibling("done.txt"));        System.out.println(Path.of("data").resolve("a.txt"));    }}

Разделитель путей зависит от системы, поэтому собирайте пути через Path.of(...) и resolve.

Чтение текстового файла

import java.io.IOException;import java.nio.charset.StandardCharsets;import java.nio.file.Files;import java.nio.file.Path;import java.util.List;public class ReadText {    public static void main(String[] args) throws IOException {        Path file = Path.of("notes.txt");        String all = Files.readString(file, StandardCharsets.UTF_8);        System.out.println(all);        List<String> lines = Files.readAllLines(file);        for (String line : lines) {            System.out.println(line);        }    }}

Для больших файлов читайте построчно потоком:

import java.io.IOException;import java.nio.file.Files;import java.nio.file.Path;import java.util.stream.Stream;public class ReadLines {    public static void main(String[] args) throws IOException {        try (Stream<String> lines = Files.lines(Path.of("big.txt"))) {            long count = lines.filter(l -> l.contains("ERROR")).count();            System.out.println(count);        }    }}

Поток Files.lines нужно закрывать, поэтому используется try-with-resources.

Запись текстового файла

import java.io.IOException;import java.nio.file.Files;import java.nio.file.Path;import java.nio.file.StandardOpenOption;import java.util.List;public class WriteText {    public static void main(String[] args) throws IOException {        Path file = Path.of("output.txt");        Files.writeString(file, "Первая строка\n");        Files.writeString(file, "Вторая строка\n", StandardOpenOption.APPEND);        Files.write(file, List.of("Третья", "Четвертая"), StandardOpenOption.APPEND);        System.out.println(Files.readString(file));    }}

По умолчанию файл создается или перезаписывается. Для дописывания используйте StandardOpenOption.APPEND.

Буферизованные чтение и запись

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.nio.file.Files;import java.nio.file.Path;public class Buffered {    public static void main(String[] args) throws IOException {        Path file = Path.of("buffered.txt");        try (BufferedWriter writer = Files.newBufferedWriter(file)) {            for (int i = 1; i <= 3; i++) {                writer.write("Строка " + i);                writer.newLine();            }        }        try (BufferedReader reader = Files.newBufferedReader(file)) {            String line;            while ((line = reader.readLine()) != null) {                System.out.println(line);            }        }    }}

Работа с файлами и каталогами

import java.io.IOException;import java.nio.file.Files;import java.nio.file.Path;import java.nio.file.StandardCopyOption;public class FileOps {    public static void main(String[] args) throws IOException {        Path dir = Path.of("workspace", "reports");        Files.createDirectories(dir);        Path file = dir.resolve("report.txt");        if (!Files.exists(file)) {            Files.createFile(file);        }        Files.writeString(file, "данные");        System.out.println(Files.size(file));        System.out.println(Files.isDirectory(dir));        System.out.println(Files.isRegularFile(file));        Path copy = dir.resolve("copy.txt");        Files.copy(file, copy, StandardCopyOption.REPLACE_EXISTING);        Path moved = dir.resolve("moved.txt");        Files.move(copy, moved, StandardCopyOption.REPLACE_EXISTING);        Files.delete(moved);        Files.deleteIfExists(file);    }}

Список и обход каталога

import java.io.IOException;import java.nio.file.Files;import java.nio.file.Path;import java.util.stream.Stream;public class ListDir {    public static void main(String[] args) throws IOException {        try (Stream<Path> entries = Files.list(Path.of("."))) {            entries.forEach(p -> System.out.println(p.getFileName()));        }        try (Stream<Path> tree = Files.walk(Path.of("."), 3)) {            tree.filter(Files::isRegularFile)                .filter(p -> p.toString().endsWith(".java"))                .forEach(System.out::println);        }    }}

Files.list показывает один уровень, Files.walk обходит вложенные каталоги.

Рекурсивное удаление каталога

import java.io.IOException;import java.nio.file.Files;import java.nio.file.Path;import java.util.Comparator;import java.util.stream.Stream;public class DeleteTree {    static void deleteRecursively(Path root) throws IOException {        try (Stream<Path> tree = Files.walk(root)) {            tree.sorted(Comparator.reverseOrder()).forEach(p -> {                try {                    Files.delete(p);                } catch (IOException e) {                    throw new RuntimeException(e);                }            });        }    }    public static void main(String[] args) throws IOException {        deleteRecursively(Path.of("workspace"));    }}

Сортировка в обратном порядке гарантирует, что вложенные элементы удаляются раньше родительских каталогов.

Двоичные данные

import java.io.IOException;import java.nio.file.Files;import java.nio.file.Path;import java.util.Arrays;public class Binary {    public static void main(String[] args) throws IOException {        Path file = Path.of("data.bin");        byte[] bytes = {1, 2, 3, (byte) 255};        Files.write(file, bytes);        byte[] read = Files.readAllBytes(file);        System.out.println(Arrays.toString(read));    }}

Для потокового чтения используйте InputStream и OutputStream:

import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.nio.file.Files;import java.nio.file.Path;public class CopyStreams {    public static void main(String[] args) throws IOException {        try (InputStream in = Files.newInputStream(Path.of("source.bin"));             OutputStream out = Files.newOutputStream(Path.of("target.bin"))) {            in.transferTo(out);        }    }}

Кодировки

Всегда указывайте кодировку явно, если работаете с текстом в разных системах:

String text = Files.readString(Path.of("a.txt"), StandardCharsets.UTF_8);Files.writeString(Path.of("b.txt"), text, StandardCharsets.UTF_8);

С Java 18 UTF-8 используется по умолчанию, но явное указание не мешает.

Properties

Простой формат конфигурации ключ=значение:

import java.io.IOException;import java.io.Reader;import java.io.Writer;import java.nio.file.Files;import java.nio.file.Path;import java.util.Properties;public class PropertiesDemo {    public static void main(String[] args) throws IOException {        Path file = Path.of("app.properties");        Properties out = new Properties();        out.setProperty("host", "localhost");        out.setProperty("port", "8080");        try (Writer writer = Files.newBufferedWriter(file)) {            out.store(writer, "Настройки");        }        Properties in = new Properties();        try (Reader reader = Files.newBufferedReader(file)) {            in.load(reader);        }        System.out.println(in.getProperty("host"));        System.out.println(Integer.parseInt(in.getProperty("port", "80")));    }}

Сериализация объектов

Интерфейс-маркер Serializable разрешает записывать объект в поток байтов:

import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;import java.nio.file.Files;import java.nio.file.Path;public class SerializationDemo {    static class Profile implements Serializable {        private static final long serialVersionUID = 1L;        String name;        int level;        transient String password;        Profile(String name, int level, String password) {            this.name = name;            this.level = level;            this.password = password;        }    }    public static void main(String[] args) throws IOException, ClassNotFoundException {        Path file = Path.of("profile.ser");        try (ObjectOutputStream out = new ObjectOutputStream(Files.newOutputStream(file))) {            out.writeObject(new Profile("Анна", 7, "secret"));        }        try (ObjectInputStream in = new ObjectInputStream(Files.newInputStream(file))) {            Profile p = (Profile) in.readObject();            System.out.println(p.name + " " + p.level + " " + p.password);        }    }}

Поле transient не сериализуется, поэтому password после чтения равен null. Не десериализуйте данные из недоверенных источников: это известный вектор атак. Для обмена данными предпочитайте JSON.

Устаревший класс File

В старом коде встречается java.io.File. Его можно преобразовать в современный API:

import java.io.File;import java.nio.file.Path;public class Legacy {    public static void main(String[] args) {        File file = new File("notes.txt");        Path path = file.toPath();        File back = path.toFile();        System.out.println(file.exists() + " " + back.getName());    }}