JavaRush /Курсы /JAVA 25 SELF /Чтение и запись файлов: базовые операции

Чтение и запись файлов: базовые операции

JAVA 25 SELF
35 уровень , 2 лекция
Открыта

1. Чтение файла целиком

Чтение всех байтов

Иногда нужно вытащить из файла всё содержимое разом — как есть, без разбора, будь то картинка, архив или какой-нибудь бинарный формат. Для этого в Java есть метод Files.readAllBytes(path). Он возвращает массив байт (byte[]), то есть просто сырые данные файла, которые вы дальше можете использовать как угодно.

import java.nio.file.*;

public class ReadBytesExample {
    public static void main(String[] args) throws Exception {
        Path path = Paths.get("example.txt");
        byte[] allBytes = Files.readAllBytes(path);
        System.out.println("Длина файла в байтах: " + allBytes.length);
    }
}

Примечание: Если файл большой (гигабайты), такой подход может привести к проблемам с памятью — ведь всё содержимое файла загружается сразу в оперативку.

Чтение всех строк

Для текстовых файлов есть более человечный способ: Files.readAllLines(path). Он возвращает список строк (List<String>), где каждая строка — это одна строка из файла (разделители строк автоматически учитываются).

import java.nio.file.*;
import java.util.List;

public class ReadLinesExample {
    public static void main(String[] args) throws Exception {
        Path path = Paths.get("example.txt");
        List<String> lines = Files.readAllLines(path);

        for (String line : lines) {
            System.out.println(line);
        }
    }
}

Важно: По умолчанию используется системная кодировка. Если вы хотите явно указать кодировку (например, UTF-8), используйте перегруженную версию метода:

List<String> lines = Files.readAllLines(path, java.nio.charset.StandardCharsets.UTF_8);

Пример: читаем файл и выводим на экран

Давайте добавим это в наше мини-приложение (например, «блокнот» или «список задач»):

import java.nio.file.*;
import java.util.List;

public class TodoReader {
    public static void main(String[] args) throws Exception {
        Path todoPath = Paths.get("todo.txt");
        if (Files.exists(todoPath)) {
            List<String> tasks = Files.readAllLines(todoPath);
            System.out.println("Ваши задачи на сегодня:");
            for (String task : tasks) {
                System.out.println("- " + task);
            }
        } else {
            System.out.println("Файл todo.txt не найден. Создайте список задач!");
        }
    }
}

2. Запись в файл

Запись массива байт

Если у вас есть массив байт (например, результат сериализации, изображение, аудио), используйте Files.write(path, bytes). Этот метод создаёт файл, если его нет, или перезаписывает существующий.

import java.nio.file.*;

public class WriteBytesExample {
    public static void main(String[] args) throws Exception {
        Path path = Paths.get("output.bin");
        byte[] data = {1, 2, 3, 4, 5};
        Files.write(path, data);
        System.out.println("Байты записаны в файл output.bin");
    }
}

Запись списка строк

Для текстовых файлов удобнее использовать список строк — каждая строка будет записана отдельно, с переводом строки.

import java.nio.file.*;
import java.util.Arrays;
import java.util.List;

public class WriteLinesExample {
    public static void main(String[] args) throws Exception {
        Path path = Paths.get("todo.txt");
        List<String> tasks = Arrays.asList(
            "Купить молоко",
            "Позвонить бабушке",
            "Сделать домашку по Java"
        );
        Files.write(path, tasks);
        System.out.println("Список задач записан в todo.txt");
    }
}

Внимание: По умолчанию файл будет перезаписан! Если он уже существовал, старые задачи исчезнут. (Как не потерять старое — расскажем чуть позже.)

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

Если хочется записать одну строку — просто создайте список из одной строки или используйте Files.write(path, string.getBytes()):

import java.nio.file.*;

public class WriteStringExample {
    public static void main(String[] args) throws Exception {
        Path path = Paths.get("hello.txt");
        String message = "Привет, Java!";
        Files.write(path, message.getBytes());
        System.out.println("Строка записана в hello.txt");
    }
}

Явное указание кодировки

Чтобы избежать «кракозябр» при работе с русским (и не только) текстом, всегда указывайте кодировку:

import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.List;

public class WriteLinesUtf8Example {
    public static void main(String[] args) throws Exception {
        Path path = Paths.get("hello.txt");
        List<String> lines = List.of("Привет, мир!", "Это Java.");
        Files.write(path, lines, StandardCharsets.UTF_8);
    }
}

3. Обработка ошибок

При работе с файлами Java может выбросить исключение IOException. Это общий сигнал о том, что «что-то пошло не так» на уровне ввода-вывода. Причин может быть масса: файла просто нет, прав доступа не хватает, диск переполнен или занят, а иногда даже флешку выдернули в самый неподходящий момент.

Поэтому методы чтения и записи файлов всегда требуют от нас готовности обработать такие ситуации. Делается это через try-catch:

import java.nio.file.*;
import java.util.List;
import java.io.IOException;

public class SafeReadExample {
    public static void main(String[] args) {
        Path path = Paths.get("todo.txt");
        try {
            List<String> lines = Files.readAllLines(path);
            System.out.println("Содержимое файла:");
            for (String line : lines) {
                System.out.println(line);
            }
        } catch (IOException ex) {
            System.out.println("Ошибка при чтении файла: " + ex.getMessage());
        }
    }
}

Зачем всё это?

try-catch превращает потенциальный крах программы в контролируемую ситуацию. Если файла нет — мы спокойно сообщим пользователю. Если система не даёт доступ — укажем на проблему. А если диск исчезнет посреди операции, программа не рухнет с жутким стек-трейсом, а хотя бы предупредит нормальным сообщением. Иначе говоря: IOException — это не враг, а просто способ Java сказать нам: «эй, тут снаружи что-то пошло не так, придумай, что делать дальше».

4. Практические примеры

Прочитать файл и вывести содержимое

import java.nio.file.*;
import java.util.List;
import java.io.IOException;

public class PrintFileExample {
    public static void main(String[] args) {
        Path path = Paths.get("notes.txt");
        try {
            if (!Files.exists(path)) {
                System.out.println("Файл notes.txt не найден.");
                return;
            }
            List<String> lines = Files.readAllLines(path, java.nio.charset.StandardCharsets.UTF_8);
            System.out.println("Содержимое файла notes.txt:");
            for (String line : lines) {
                System.out.println(line);
            }
        } catch (IOException e) {
            System.out.println("Ошибка при чтении файла: " + e.getMessage());
        }
    }
}

Записать строку в новый файл

import java.nio.file.*;
import java.nio.charset.StandardCharsets;
import java.io.IOException;

public class WriteFileExample {
    public static void main(String[] args) {
        Path path = Paths.get("greeting.txt");
        String content = "Добро пожаловать в мир Java IO!";
        try {
            Files.write(path, content.getBytes(StandardCharsets.UTF_8));
            System.out.println("Строка записана в файл greeting.txt");
        } catch (IOException e) {
            System.out.println("Ошибка при записи файла: " + e.getMessage());
        }
    }
}

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

import java.nio.file.*;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.io.IOException;

public class WriteListExample {
    public static void main(String[] args) {
        Path path = Paths.get("shopping.txt");
        List<String> items = List.of("Хлеб", "Молоко", "Сыр");
        try {
            Files.write(path, items, StandardCharsets.UTF_8);
            System.out.println("Список покупок записан в shopping.txt");
        } catch (IOException e) {
            System.out.println("Ошибка при записи файла: " + e.getMessage());
        }
    }
}

5. Кратко о потоках

Методы Files.readAllBytes, Files.readAllLines, Files.write — это «всё и сразу»: либо весь файл в память, либо всё содержимое сразу на диск. Для небольших файлов это удобно, а для больших — не очень (можно получить OutOfMemoryError или просто «зависнуть» на чтении гигабайтных логов).

Для работы с большими файлами или построчного чтения используют потоки:

  • Для текста: BufferedReader, BufferedWriter
  • Для байтов: InputStream, OutputStream

Подробнее о потоках мы поговорим в следующих лекциях, но вот маленький тизер:

import java.nio.file.*;
import java.io.*;

public class BufferedReaderExample {
    public static void main(String[] args) {
        Path path = Paths.get("bigfile.txt");
        try (BufferedReader reader = Files.newBufferedReader(path)) {
            String line;
            while ((line = reader.readLine()) != null) {
                // Обрабатываем строку
                System.out.println(line);
            }
        } catch (IOException e) {
            System.out.println("Ошибка при чтении файла: " + e.getMessage());
        }
    }
}

6. Полезные нюансы

  • Перезапись файла: Все методы Files.write по умолчанию перезаписывают файл. Если нужно добавить в конец, используйте дополнительные опции (об этом — в следующей лекции).
  • Кодировка: Всегда указывайте кодировку явно, если работаете с не-ASCII текстом. Это избавит от «кракозябр» на выходе. Хороший выбор — StandardCharsets.UTF_8.
  • Пути: Используйте Paths.get(...) для кроссплатформенности. Никогда не хардкодьте слэши (/ или \) вручную.
  • Имена файлов: Не используйте в имени файла запрещённые символы (?, *, :, <, >, | и т.д.), особенно если ваш код должен работать на Windows.

7. Типичные ошибки при чтении и записи файлов

Ошибка №1: Не обрабатывается IOException. Очень часто новички пишут Files.readAllLines(path) без try-catch, и при первой же проблеме (файл не найден, нет прав, повреждён диск) программа падает. Всегда обрабатывайте исключения!

Ошибка №2: Работа с большими файлами через readAllBytes/readAllLines. Если файл весит сотни мегабайт или гигабайты, попытка загрузить его целиком может «убить» вашу программу. Для таких случаев используйте потоки (BufferedReader).

Ошибка №3: Не указана кодировка при записи/чтении текста. Если не указать кодировку, на разных компьютерах и ОС результат может отличаться. Особенно часто проблема проявляется с кириллицей. Используйте StandardCharsets.UTF_8 или нужную вам кодировку явно.

Ошибка №4: Ожидание, что File/Path — это сам файл. Класс File или Path — это только «ярлык» на файл, а не сам файл. Создав объект, вы не создаёте файл на диске. Чтобы создать файл — используйте методы Files.createFile, Files.write и так далее.

Ошибка №5: Не закрывается поток (если используете потоки). Если вы используете потоки вручную (например, BufferedReader), обязательно закрывайте их (лучше через try-with-resources). Иначе файл может остаться «залоченным» и недоступным для других программ.

1
Задача
JAVA 25 SELF, 35 уровень, 2 лекция
Недоступна
Сколько места занимает ваш "секретный" документ? 📜
Сколько места занимает ваш "секретный" документ? 📜
1
Задача
JAVA 25 SELF, 35 уровень, 2 лекция
Недоступна
Просмотр журнала событий системы 💻
Просмотр журнала событий системы 💻
Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Shanechka Уровень 54
27 декабря 2025
Пример решения первой задачки ужас, такое еще не проходили, сделала так:

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.charset.StandardCharsets;

public class Solution {
    public static void main(String[] args) throws Exception {
        Path path = Path.of("encrypted_message.bin");
        Files.write(path, "hahaha".getBytes(StandardCharsets.UTF_8));
        byte[] allbytes = Files.readAllBytes(path);
        System.out.printf("Размер документа: %d байт", allbytes.length);
    }
}