Автор статьи: Сергей Прощаев (@sproshchaev), Руководитель направления Java‑разработки в FinTech
Введение
Многие наверняка сталкивались с ситуацией, когда при открытии файла в текстовом редакторе (например, Word) вместо ожидаемого текста появляется хаотичный набор символов: или «кракозябры». Такое происходит, когда программа неправильно определяет кодировку файла — набор правил, по которым символы преобразуются в двоичный код.
Каждый формат файла (TXT, DOCX, PDF и другие) имеет свою структуру и использует определённую кодировку для хранения данных. Если приложение неверно интерпретирует эти правила, текст становится нечитаемым.
Кодировки или как компьютеры понимают наш язык?
Когда вы печатаете сообщение или читаете статью в интернете, ваш компьютер видит не буквы, а комбинации нулей и единиц. Чтобы превратить эти биты в понятный текст, нужны таблицы кодировок — своего рода «переводчики» между человеческим языком и машинным кодом.
Представьте, что компьютер — это иностранец, который понимает только цифры. Чтобы объяснить ему, что означает буква «А» или символ «!», нужен словарь. Таблица кодировки как раз и является таким словарем: она сопоставляет каждому символу (букве, цифре, эмодзи) уникальный числовой код. Этот код затем преобразуется в байты — минимальные единицы данных, которые компьютер может хранить или передать.
Процесс кодирования состоит из двух шагов.
На первом шаге кодирования символ преобразуется в числовой код. Например, в кодировке ASCII (American Standard Code for Information Interchange) буква A имеет код 65.
Почему 65? Давайте разберемся. В основе этого преобразования лежит система счисления с основанием числа 2 или двоичная система.

Каждая ячейка на рис.1 — это «бит» (0 или 1). Биты соответствуют степеням числа 2: 64 = 2⁶, 32 = 2⁵, 16 = 2⁴, 8 = 2³, 4 = 2², 2 = 2¹, 1 = 2⁰. Как читать двоичное число? Если под числом стоит 1 — оно включено в сумму, если 0 — исключено. На слайде: 64 (2⁶) = 1 → берём 64 32, 16, 8, 4, 2 = 0 → не берём 1 (2⁰) = 1 → берём 1. Теперь складываем выбранные числа: 64 + 1 = 65.
На втором шаге кодирования код 65 преобразуется в последовательность байтов. В ASCII буква A становится байтом 1 000 001. На рис.1 это цифры 1 и 0 красного цвета.
И теперь эти семь бит 1 000 001 мы можем поместить в специальную таблицу, которую называют таблицей кодировок.
Таблицы кодировок
Таблиц кодировок было изобретено множество. Таблица ASCII (American Standard Code for Information Interchange), представленная на рис.2, была создана в 1960-х годах и изначально предназначалась для англоязычных пользователей.

ASCII использует 7 бит данных, что позволяет закодировать всего 128 символов — этого хватает для английского алфавита (заглавные и строчные буквы), цифр, знаков препинания и управляющих команд (например, «перевод строки»). И как раз наша английская буква A, закодированная как 1 000 001 может быть помещена в эту таблицу.
Как в Java можно прочитать и записать произвольную строку символов в файл?
Допустим, мы хотим сохранить фразу «Hello, World!» в файл. Вот как это можно сделать:
import java.io.*; public class WriteFileDefaultEncoding { public static void main(String[] args) { String text = "Hello, World!"; try (Writer writer = new BufferedWriter( new FileWriter("default_file.txt"))) { writer.write(text); System.out.println("Файл записан с кодировкой по умолчанию."); } catch (IOException e) { System.out.println("Ошибка: " + e.getMessage()); } } }
Как это работает все вместе? FileReader открывает файл default_file.txt и пытается прочитать его в кодировке системы. BufferedReader считывает данные блоками (в данном примере — по 1024 символа за раз). StringBuilder собирает все считанные части в одну строку, а try‑with‑resources автоматически закрывает поток после чтения, даже если произошла ошибка.
В этом примере используются классы из пакета java.io. Класс FileWriter записывает текст в файл, используя кодировку по умолчанию. Класс BufferedWriter оборачивает FileWriter для буферизации данных. Использование буферизации увеличивает скорость записи, так как данные сначала накапливаются в памяти (буфере), а затем записываются в файл большими порциями. Writer представляет собой абстрактный класс, который является базовым для всех классов, записывающих символы в поток. Если произойдёт ошибка (например, файл заблокирован другим процессом), будет выброшено исключение IOException, и программа выведет сообщение об ошибке.
Теперь выполним обратную операцию и прочитаем файл default_file.txt, созданный в предыдущем примере, и отобразим его содержимое в консоль:
import java.io.*; public class ReadFileDefaultEncoding { public static void main(String[] args) { try (Reader reader = new BufferedReader( new FileReader("default_file.txt"))) { char[] buffer = new char[1024]; int length; StringBuilder content = new StringBuilder(); while ((length = reader.read(buffer)) != -1) { content.append(buffer, 0, length); } System.out.println("Содержимое файла: " + content.toString()); } catch (IOException e) { System.out.println("Ошибка: " + e.getMessage()); } } }
FileReader открывает файл default_file.txt и пытается прочитать его в кодировке системы. BufferedReader считывает данные блоками (в данном примере — по 1024 символа за раз). StringBuilder собирает все считанные части в одну строку.
Какие классы используются здесь? FileReader читает текст из файла, используя кодировку по умолчанию. BufferedReader оборачивает FileReader для буферизации данных. Данные, при использовании BufferedReader считываются большими блоками, а не по одному символу. Reader это абстрактный класс, базовый для всех классов, считывающих символы из потока.
Заключение
Понимание кодировок — основа работы с текстом в Java и любом другом языке программирования. Кодировки определяют, как символы (буквы, цифры, знаки) преобразуются в двоичный код, который понимает компьютер. Без этого знания даже простые операции — например, чтение файла или вывод строки на экран — могут привести к ошибкам.
Если вы хотите углубить свои знания в области работы с данными, оптимизации процессов или улучшения архитектуры приложений, обратите внимание на следующие открытые онлайн-уроки. Они помогут разобраться в актуальных аспектах технологий и понять, как они применяются в реальных проектах:
27 мая 20:00 — Паттерны RESTful API
28 мая 20:00 — Основы сжатия данных: создаем RLE архиватор
10 июня 20:00 — Журналирование в ОС Linux
Больше актуальных навыков по разработке и работе с данными вы можете получить в рамках практических онлайн-курсов от экспертов отрасли.
