Ввод-вывод и файлы в Java
Ввод-вывод и файлы
★ Ввод-вывод (I/O) в Java строится на потоках: последовательная передача байтов или символов между программой и источником (файл, сеть, консоль). Современный API файловой системы — NIO.2 (java.nio.file, с Java 7).
Исключения при I/O: обработка исключений. Строки и кодировки: строки.
Два уровня API
| Уровень | Пакеты | Назначение |
|---|---|---|
| Классический I/O | java.io | InputStream, OutputStream, Reader, Writer |
| NIO / NIO.2 | java.nio, java.nio.file | Буферы, каналы, Path, Files |
В новом коде для файлов на диске начинайте с Path + Files, для сети и бинарных протоколов — потоки или NIO channels.
Path и Files (NIO.2)
Path — неизменяемый путь (замена устаревшему java.io.File для логики путей):
Path config = Path.of("app", "config", "settings.properties");
Path absolute = config.toAbsolutePath().normalize();
boolean exists = Files.exists(config);
boolean isDir = Files.isDirectory(config);
long size = Files.size(config);
Чтение и запись целиком (малые и средние файлы):
Path file = Path.of("notes.txt");
List<String> lines = Files.readAllLines(file, StandardCharsets.UTF_8);
String text = Files.readString(file, StandardCharsets.UTF_8);
Files.writeString(file, "новая строка\n", StandardCharsets.UTF_8,
StandardOpenOption.CREATE, StandardOpenOption.APPEND);
Поток строк (большие файлы, ленивая обработка):
try (Stream<String> lines = Files.lines(file, StandardCharsets.UTF_8)) {
long count = lines.filter(l -> !l.isBlank()).count();
}
Копирование и перемещение:
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
Files.move(oldPath, newPath);
Files.delete(path);
Files.createDirectories(Path.of("data", "cache"));
Байтовые и символьные потоки
| Тип | Классы | Единица |
|---|---|---|
| Байтовый | InputStream, OutputStream | byte |
| Символьный | Reader, Writer | char (кодировка) |
Символьные потоки оборачивают байтовые с указанием charset:
try (Reader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8);
Writer writer = Files.newBufferedWriter(out, StandardCharsets.UTF_8)) {
char[] buf = new char[8192];
int n;
while ((n = reader.read(buf)) != -1) {
writer.write(buf, 0, n);
}
}
Буферизация (BufferedInputStream, BufferedReader) снижает число системных вызовов.
try-with-resources
Ресурсы, реализующие AutoCloseable, закрываются автоматически:
try (InputStream in = Files.newInputStream(path);
OutputStream out = Files.newOutputStream(target)) {
in.transferTo(out); // Java 9+
}
При исключении в блоке сначала выбрасывается основное, затем подавленное из close() — удобно для диагностики.
Связь с try-with-resources для исключений.
Сериализация объектов (кратко)
ObjectOutputStream / ObjectInputStream сохраняют граф объектов в бинарный поток. Класс должен реализовать Serializable (или Externalizable).
В современных системах чаще используют JSON/XML/Protobuf (см. стандартные библиотеки), а не Java Serialization — из соображений безопасности и совместимости версий.
Работа с каталогами
try (Stream<Path> walk = Files.walk(Path.of("logs"), 2)) {
walk.filter(Files::isRegularFile)
.filter(p -> p.toString().endsWith(".log"))
.forEach(System.out::println);
}
Files.list(dir) — только один уровень; walk — рекурсия с лимитом глубины.
Типичные ошибки
- Не указана кодировка —
FileReaderбез charset использует платформенную; на Windows часто не UTF-8. - Утечка дескрипторов — поток не закрыт (нет try-with-resources).
- Чтение гигантского файла в
readAllLines— рискOutOfMemoryError; используйтеFiles.linesили буфер. - Относительные пути — зависят от
user.dir; для конфигов лучше явный базовый каталог или переменные окружения. - Пути с пробелами —
Path.ofкорректен; не склеивайте строки вручную через\.
I/O и многопоточность
Блокирующее чтение в одном потоке занимает поток ОС на всё время ожидания диска или сети. Для множества одновременных соединений смотрите асинхронность и NIO (Selector, неблокирующие каналы) или фреймворки уровня Spring WebFlux.
Связанные материалы
- Обработка исключений
- Строки в Java
- Stream API
- JVM, память и потоки
- Справочник по конфигурациям — кодировки и
java.io.tmpdir
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). Основы Java - устройство JDK/JVM, модель компиляции и базовые принципы платформонезависимого выполнения. Java — это объектно-ориентированный язык программирования общего назначения, который работает на принципах «напиши один раз, запускай в любом месте». Набор советов, правил, принципов и обычаев в разработке на этом языке. История Java — от проекта Green и Oak до OpenJDK, LTS-релизов и современной платформы (модули, records, виртуальные потоки). Библиотеки, фреймворки, инструменты сборки, тестирования, развёртывания и мониторинга. Что такое пакет и пакетная структура, как собираются проекты на Java. Справочник-шпаргалка по конфигурациям в Java — типы, синтаксис, стандартная библиотека, типовые паттерны. Не заменяет пошаговое обучение. Учебный курс — раздел. Гайд по установке и настройке с написанием первой программы и её запуском. Практические примеры — консольные утилиты, композиция классов в мини-игре и первое Swing-приложение. Точки останова, пошаговое выполнение, панели Variables и Call Stack — практика отладки в IntelliJ IDEA. Кавычки, точки, запятые, скобки и прочие знаки препинания. Это полный справочник всех ключевых слов языка Java, включая основные, контекстные и зарезервированные слова.Основы языка Java
Что требуется знать перед началом изучения языка программирования Java
Рекомендации по разработке на Java
История языка Java
Экосистема Java-приложений
Структура и сборки Java-проектов
Справочник по конфигурациям в Java
Первая программа на Java
Простые приложения на Java
Отладка Java-кода в IDE
Синтаксис и пунктуация в Java
Ключевые слова в Java