FileReader: примеры (JAVA)
FileReader(File file, String fileName)Общее описание и сигнатуры
Класс java.io.FileReader предназначен для чтения текстовых данных из файлов как поток символов. FileReader наследуется от InputStreamReader и использует системную кодировку по умолчанию для преобразования байтов в символы. Частое применение - простое посимвольное или по-блочно чтение текстовых файлов в кодировке по умолчанию.
Конструкторы
- FileReader(String fileName) - открывает файл по имени; выбрасывает FileNotFoundException, если файл не найден.
- FileReader(File file) - открывает файл по объекту java.io.File.
- FileReader(FileDescriptor fd) - использует существующий файловый дескриптор.
Основные методы
- int read() - читает один символ и возвращает его как целое значение (0..65535), при достижении конца возвращает -1.
- int read(char[] cbuf) - пытается заполнить массив символов, возвращает число реально прочитанных символов или -1.
- int read(char[] cbuf, int off, int len) - читает до len символов в cbuf, начиная с off, возвращает количество прочитанных символов или -1.
- void close() - закрывает поток и освобождает ресурс; рекомендуется использовать try-with-resources.
- При ошибках может выбрасываться IOException и дочерние (FileNotFoundException, UnsupportedEncodingException не напрямую от FileReader, но при работе с кодировками через InputStreamReader).
Особенности
- FileReader использует кодировку по умолчанию платформы; это делает поведение зависимым от окружения и может привести к некорректной обработке файлов в известной кодировке. Для явного указания кодировки лучше применять InputStreamReader с явным Charset или java.nio.file.Files.newBufferedReader(Path, Charset).
- FileReader - символьный поток; не подходит для бинарных данных.
Короткие примеры применения
1. Базовое чтение символов
import java.io.FileReader;
import java.io.IOException;
public class Example1 {
public static void main(String[] args) throws IOException {
try (FileReader fr = new FileReader("example.txt")) {
int ch;
while ((ch = fr.read()) != -1) {
System.out.print((char) ch);
}
}
}
}
(содержимое файла example.txt выводится посимвольно) Пример текста 123
2. Чтение блоком в буфер
import java.io.FileReader;
import java.io.IOException;
public class Example2 {
public static void main(String[] args) throws IOException {
try (FileReader fr = new FileReader("example.txt")) {
char[] buf = new char[32];
int n;
while ((n = fr.read(buf)) != -1) {
System.out.print(new String(buf, 0, n));
}
}
}
}
(тот же вывод, но читается блоками) Пример текста 123
3. Чтение строк через BufferedReader
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Example3 {
public static void main(String[] args) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
}
}
Пример текста 123
4. Обработка отсутствия файла
import java.io.FileReader;
import java.io.IOException;
public class Example4 {
public static void main(String[] args) {
try (FileReader fr = new FileReader("no_such_file.txt")) {
// ...
} catch (IOException e) {
System.out.println("Ошибка: " + e.getClass().getSimpleName() + " - " + e.getMessage());
}
}
}
Ошибка: FileNotFoundException - no_such_file.txt (No such file or directory)
Альтернативы в Java и их особенности
- BufferedReader
- InputStreamReader + FileInputStream
- Files.newBufferedReader(Path, Charset)
- Files.readAllLines / Files.readString
- FileInputStream
- Scanner
Часто комбинируется с FileReader для эффективного построчного чтения. Предпочтителен при работе со строками и при необходимости метода readLine().
Позволяет явно указать кодировку: new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8). Предпочтительнее для портативности кодировок.
Современный NIO API. Удобен для указания Charset и работы с Path.
Читают весь файл целиком. Удобно для небольших файлов, но не для больших по памяти.
Для побайтовой работы. Применяется при обработке бинарных данных.
Удобен для разбора токенов и парсинга по разделителям, но медленнее и тяжелее для простого чтения строк.
Аналоги в других языках и отличия
PHP
// file_get_contents
$txt = file_get_contents('example.txt');
echo $txt;
Пример текста 123
Отличие: PHP по умолчанию читает байты и возвращает строку в своей внутренней кодировке; явное указание кодировки может потребоваться при работе с multibyte.
JavaScript (Node.js)
const fs = require('fs');
const txt = fs.readFileSync('example.txt', 'utf8');
console.log(txt);
Пример текста 123
Отличие: в Node.js кодировка указывается явно (например, 'utf8').
Python
with open('example.txt', 'r', encoding='utf-8') as f:
print(f.read())
Пример текста 123
Отличие: в Python рекомендуется всегда указывать encoding для предсказуемости.
C#
using System.IO;
var text = File.ReadAllText("example.txt");
Console.WriteLine(text);
Пример текста 123
Отличие: StreamReader позволяет указать Encoding; File.ReadAllText по умолчанию использует UTF-8 в современных версиях .NET, но поведение платформозависимо в старых релизах.
Go
package main
import (
"fmt"
"io/ioutil"
)
func main() {
b, _ := ioutil.ReadFile("example.txt")
fmt.Print(string(b))
}
Пример текста 123
Отличие: Go работает с байтами и преобразование в строку предполагает UTF-8.
Kotlin
import java.io.File
fun main() {
println(File("example.txt").readText())
}
Пример текста 123
Отличие: Kotlin использует JVM API, есть удобные расширения для чтения с указанием Charset.
Lua
local f = io.open('example.txt', 'r')
local s = f:read('*a')
f:close()
print(s)
Пример текста 123
Отличие: меньше встроенной поддержки кодировок; требуется внешняя обработка для Unicode.
Типичные ошибки при использовании
- Файл не найден (FileNotFoundException)
new FileReader("missing.txt");
java.io.FileNotFoundException: missing.txt (No such file or directory)
Ожидание UTF-8 при чтении файла в другой кодировке приводит к искажённым символам. FileReader не позволяет указать кодировку напрямую.
// файл в UTF-8, но среда использует другую кодировку
try (FileReader fr = new FileReader("utf8file.txt")) {
int c = fr.read();
// ...
}
вывод могут содержать кракозябры вместо ожидаемых кириллических букв
FileReader fr = new FileReader("example.txt");
fr.read();
// fr.close() может не вызваться при исключении
Плавающие дескрипторы файла, исчерпание ресурсов при большом числе открытых файлов
read(buf) не гарантирует полного заполнения массива; нужно проверять возвращаемое значение.
char[] buf = new char[100];
int n = fr.read(buf);
System.out.println(new String(buf)); // может содержать старые символы в конце
Вывод может содержать мусор после n символов; правильнее new String(buf,0,n)
Изменения и современные рекомендации
Класс FileReader сам по себе в Java изменялся мало и остаётся простым символьным адаптером для файлов. Основные эволюционные изменения связаны с появлением NIO.2 (Java 7) и классов в java.nio.file.Files, которые предлагают более гибкую работу с Path и Charset. В современной практике рекомендуется:
- Для явного указания кодировки использовать Files.newBufferedReader(Path, Charset) или new InputStreamReader(new FileInputStream(file), charset).
- Для больших файлов применять потоковую обработку через BufferedReader.lines() или стримы NIO.
Непосредственно методы FileReader не были объявлены устаревшими и остаются доступными.
Продвинутые и редкие сценарии
1. Явное указание кодировки через InputStreamReader
import java.io.*;
import java.nio.charset.StandardCharsets;
public class Adv1 {
public static void main(String[] args) throws IOException {
try (InputStreamReader isr = new InputStreamReader(new FileInputStream("example-utf8.txt"), StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(isr)) {
br.lines().forEach(System.out::println);
}
}
}
(строки файла корректно выводятся как UTF-8) Текст в UTF-8
2. Построчная обработка большого файла с подсчетом вхождений
import java.io.*;
public class Adv2 {
public static void main(String[] args) throws IOException {
long count = 0;
try (BufferedReader br = new BufferedReader(new FileReader("big.txt"))) {
String line;
while ((line = br.readLine()) != null) {
if (line.contains("ERROR")) count++;
}
}
System.out.println("ERROR lines: " + count);
}
}
ERROR lines: 42
3. Чтение части файла: смещение и длина
import java.io.*;
public class Adv3 {
public static void main(String[] args) throws IOException {
try (FileReader fr = new FileReader("example.txt")) {
fr.skip(10); // перейти на 10 символов вперёд
char[] buf = new char[20];
int n = fr.read(buf, 0, buf.length);
if (n > 0) System.out.println(new String(buf, 0, n));
}
}
}
(вывод 20 символов, начиная с позиции 11 файла)
4. Комбинация с CharsetDecoder для контроля декодирования
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
public class Adv4 {
public static void main(String[] args) throws IOException {
CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
try (FileInputStream fis = new FileInputStream("example.txt")) {
byte[] b = new byte[64];
int r;
while ((r = fis.read(b)) != -1) {
ByteBuffer bb = ByteBuffer.wrap(b, 0, r);
CharBuffer cb = decoder.decode(bb);
System.out.print(cb.toString());
}
}
}
}
(правильное декодирование UTF-8 с контролем ошибок декодера)
5. Чтение ресурсов внутри JAR
import java.io.*;
public class Adv5 {
public static void main(String[] args) throws IOException {
try (InputStream is = Adv5.class.getResourceAsStream("/resource.txt")) {
if (is == null) return;
try (InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr)) {
br.lines().forEach(System.out::println);
}
}
}
}
(содержимое resource.txt внутри JAR выводится корректно)
В расширенных сценариях часто комбинируются NIO и классы декодирования для повышения контроля над производительностью и обработкой кодировок. FileReader остаётся удобным для быстрых задач, но для критичного к кодировке и масштабируемого чтения предпочтительнее InputStreamReader, Files и NIO-подходы.