Автор статьи: Сергей Прощаев (@sproshchaev), Руководитель направления Java‑разработки в FinTech

Введение

Многие наверняка сталкивались с ситуацией, когда при открытии файла в текстовом редакторе (например, Word) вместо ожидаемого текста появляется хаотичный набор символов: или «кракозябры». Такое происходит, когда программа неправильно определяет кодировку файла — набор правил, по которым символы преобразуются в двоичный код.

Каждый формат файла (TXT, DOCX, PDF и другие) имеет свою структуру и использует определённую кодировку для хранения данных. Если приложение неверно интерпретирует эти правила, текст становится нечитаемым.

Кодировки или как компьютеры понимают наш язык?

Когда вы печатаете сообщение или читаете статью в интернете, ваш компьютер видит не буквы, а комбинации нулей и единиц. Чтобы превратить эти биты в понятный текст, нужны таблицы кодировок — своего рода «переводчики» между человеческим языком и машинным кодом.

Представьте, что компьютер — это иностранец, который понимает только цифры. Чтобы объяснить ему, что означает буква «А» или символ «!», нужен словарь. Таблица кодировки как раз и является таким словарем: она сопоставляет каждому символу (букве, цифре, эмодзи) уникальный числовой код. Этот код затем преобразуется в байты — минимальные единицы данных, которые компьютер может хранить или передать.

Процесс кодирования состоит из двух шагов.

На первом шаге кодирования символ преобразуется в числовой код. Например, в кодировке ASCII (American Standard Code for Information Interchange) буква A имеет код 65.

Почему 65? Давайте разберемся. В основе этого преобразования лежит система счисления с основанием числа 2 или двоичная система.

Рис. 1 Преобразование буквы A в число 65
Рис. 1 Преобразование буквы A в число 65

Каждая ячейка на рис.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-х годах и изначально предназначалась для англоязычных пользователей.

Рис. 2 Таблица ASCII
Рис. 2 Таблица ASCII

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 и любом другом языке программирования. Кодировки определяют, как символы (буквы, цифры, знаки) преобразуются в двоичный код, который понимает компьютер. Без этого знания даже простые операции — например, чтение файла или вывод строки на экран — могут привести к ошибкам.


Если вы хотите углубить свои знания в области работы с данными, оптимизации процессов или улучшения архитектуры приложений, обратите внимание на следующие открытые онлайн-уроки. Они помогут разобраться в актуальных аспектах технологий и понять, как они применяются в реальных проектах:

Больше актуальных навыков по разработке и работе с данными вы можете получить в рамках практических онлайн-курсов от экспертов отрасли.

Комментарии (5)


  1. skovpen
    21.05.2025 10:33

    На первом шаге кодирования символ преобразуется в числовой код. Например, в кодировке ASCII (American Standard Code for Information Interchange) буква A имеет код 65. Почему 65? Давайте разберемся.

    Задан один вопрос, а ответ на другой вопрос :-)


  1. kmatveev
    21.05.2025 10:33

    Ужасно. Один из абзацев присутствует в двух местах. Ничего толкового про кодировки не написано.


  1. Gabenskiy
    21.05.2025 10:33

    Как кодировки связаны с написанием кода без ошибок?


    1. lil_master
      21.05.2025 10:33

      Через Java!


  1. RomTec
    21.05.2025 10:33

    Очередная статья из серии "Замах - на рубль, удар - на копейку!"

    По заголовку предвкушал что-то особенное. Но в статье про обработку "кодировок" вообще не упоминается ... Unicode ! Ну хотя бы про КОИ-8 можно было сказать пару слов ?