JavaRush /Курси /JAVA 25 SELF /Що таке кодування і навіщо воно потрібне

Що таке кодування і навіщо воно потрібне

JAVA 25 SELF
Рівень 37 , Лекція 0
Відкрита

1. Поняття кодування (encoding)

Почнімо з головного питання: що таке кодування?

Уявіть, що ви приїхали на міжнародну конференцію. Кожен говорить своєю мовою, але всі хочуть порозумітися. Для цього потрібен перекладач, який знає, що слово "hello" англійською — це "привіт" українською і "hola" іспанською. У світі комп’ютерів кодування — той самий перекладач.

Кодування — це спосіб подання символів у вигляді байтів

Комп’ютер — річ проста: він розуміє лише нулі та одиниці, тобто біти й байти. А от люди хочуть бачити літери, цифри, емодзі і навіть — о, жах! — китайські ієрогліфи. Щоб комп’ютер міг «записати» символ, потрібно домовитися, якому набору байтів відповідатиме кожен символ.

Кодування (encoding) — це набір правил, за якими символи (літери, цифри, розділові знаки, емодзі тощо) перетворюються на байти для зберігання та передавання, і навпаки: байти перетворюються на символи для відображення.

Приклад: літера 'А' у різних кодуваннях

  • У кодуванні UTF-8 літера 'А' (кирилична) кодується двома байтами: 0xD0 0x90.
  • У кодуванні Windows-1251 та сама літера — один байт: 0xC0.
  • А от латинська 'A' майже в усіх популярних кодуваннях — це 0x41.

Якщо прочитати файл у неправильному кодуванні, символи перетворяться на «кракозябри» (незрозумілі знаки або знак питання).

2. Навіщо потрібні кодування

Чому не можна просто зберігати літери як є?

Тому що комп’ютер розуміє лише числа (нулі та одиниці). Яке число відповідає якій літері — це і є суть кодування.

Приклад: «Привіт» на диску

Коли ви пишете у файл слово "Привіт", для комп’ютера це просто послідовність байтів. Як ці байти інтерпретувати — залежить від кодування.

  • Якщо файл записано в UTF-8, то «П» — це два байти, «р» — теж два, і так далі.
  • Якщо у Windows-1251, то кожна літера — один байт, але значення байтів інші.

Де потрібні кодування?

  • Під час запису тексту у файл: щоб байти потім можна було правильно прочитати.
  • Під час читання тексту з файлу: щоб байти знову перетворилися на літери.
  • Під час надсилання тексту мережею (наприклад, HTTP, e‑mail).
  • Під час роботи з базами даних: там теж потрібно розуміти, у якому кодуванні зберігається текст.

Якщо не вказати кодування...

Це як відкрити текст незнайомою мовою і намагатися його прочитати. Шанси зростають, якщо ви знаєте, якою це мовою. А якщо не знати — у найкращому разі ви нічого не зрозумієте, у гіршому — отримаєте абракадабру.

3. Проблеми без правильного кодування

«Кракозябри» та втрата даних

Найчастіша скарга початківців (і не тільки) програмістів: «Чому замість "Привіт" я бачу "Привет" або взагалі самі знаки питання?»

Це відбувається, коли файл було записано в одному кодуванні, а читається в іншому. Наприклад, файл було створено на старій Windows у Windows-1251, а ви відкриваєте його в Linux, де за замовчуванням UTF-8. Або навпаки.

Приклад

  • Записали файл у Windows-1251: байт для «П» — 0xCF.
  • Відкрили в UTF-8: програма очікує, що кирилиця — це два байти, а отримує один. Усе ламається.

Втрата даних

Якщо під час запису символ не підтримується обраним кодуванням (наприклад, намагаєтеся зберегти смайлик‑емодзі в ASCII), то він зникне або заміниться на знак питання. Усе, що не «влізло» в кодування, втрачається.

Проблеми під час обміну файлами

Файли, записані в одному кодуванні, можуть відображатися некоректно на інших комп’ютерах, якщо там інше кодування за замовчуванням. Часто це трапляється під час обміну файлами між Windows і Linux або під час відкриття старих файлів.

4. Кодування в Java: внутрішнє та зовнішнє подання

Всередині JVM: завжди Unicode (UTF-16)

У Java рядки (String) всередині програми завжди зберігаються в Unicode (а точніше, у UTF-16). Це означає, що ви можете спокійно присвоювати змінним рядки будь-якою мовою світу, і Java усе це обробить.

String hello = "Привіт, світе! 😀";

У пам’яті JVM цей текст зберігається як набір 16‑бітних чисел (char), де кожному символу відповідає свій код у таблиці Unicode.

Цікавий факт
У Java символ типу char — це 16 біт (2 байти). Але деякі символи (наприклад, рідкісні ієрогліфи або емодзі) вже потребують двох char — це «сурогатні пари».

Під час введення/виведення: кодування має значення!

Коли ви читаєте або записуєте рядки у зовнішній світ (файли, мережа), Java має перетворити внутрішнє подання (UTF-16) на послідовність байтів. Ось тут і потрібне кодування.

  • Якщо ви явно не вказали кодування, Java використовує системне кодування за замовчуванням (українською Windows це може бути Windows-1251, у Linux — UTF-8).
  • Це небезпечно: на іншому комп’ютері результат може відрізнятися.

Приклад: читання і запис файлу без зазначення кодування

// Погана практика! Кодування не вказано.
FileReader reader = new FileReader("data.txt");
FileWriter writer = new FileWriter("data.txt");

У такому разі Java використовує системне кодування. Якщо файл було записано на іншій системі — отримаєте «кракозябри».

Хороша практика: завжди вказувати кодування

// Добре! Кодування явно вказано.
BufferedReader reader = new BufferedReader(
    new InputStreamReader(new FileInputStream("data.txt"), StandardCharsets.UTF_8));
BufferedWriter writer = new BufferedWriter(
    new OutputStreamWriter(new FileOutputStream("data.txt"), StandardCharsets.UTF_8));

5. Коротка ілюстрація: що відбувається під час роботи з кодуваннями

Схема: шлях рядка від файлу до програми і назад

[Файл на диску (байти, кодування X)]
        |
        V
[Java читає байти і за допомогою кодування X перетворює на String (UTF-16)]
        |
        V
[Ви працюєте з рядком у програмі]
        |
        V
[Java записує String у байти, використовуючи кодування Y]
        |
        V
[Файл на диску (байти, кодування Y)]

Якщо X і Y збігаються — усе добре. Якщо різні — можливі проблеми.

6. Коротка історія кодувань (для допитливих)

ASCII

ASCII — одне з найдавніших кодувань: один байт на символ, лише англійський алфавіт, цифри та базові знаки. Будь‑які інші абетки — не підтримуються.

Windows-1251, ISO-8859-1 та інші «старожили»

Це однобайтові кодування для різних наборів літер: кирилиця, латиниця, грецька тощо. Кожен обирав своє — і почалася плутанина.

Unicode і сімейство UTF

  • Unicode — глобальна таблиця для символів світу.
  • UTF-8, UTF-16, UTF-32 — різні способи подання символів Unicode у байтах.
  • UTF-8 став стандартом для Web, файлів і міжсистемного обміну.

7. Практика: як кодування впливає на роботу з файлами

Подивімося невеликий приклад запису та читання рядків із різними кодуваннями.

Приклад: запис і читання в різних кодуваннях

import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

public class EncodingDemo {
    public static void main(String[] args) throws IOException {
        String text = "Привіт, світе! 😀";

        // Запишемо файл у UTF-8
        try (Writer writer = new OutputStreamWriter(
                new FileOutputStream("utf8.txt"), StandardCharsets.UTF_8)) {
            writer.write(text);
        }

        // Тепер спробуємо прочитати його в неправильному кодуванні
        try (Reader reader = new InputStreamReader(
                new FileInputStream("utf8.txt"), Charset.forName("Windows-1251"))) {
            int c;
            while ((c = reader.read()) != -1) {
                System.out.print((char) c);
            }
        }
        // На екрані буде абракадабра!
    }
}

Висновок: Якщо кодування не збігаються — текст буде спотворено.

8. Кодування та інтеграція з іншими системами

У реальних проєктах файли часто обмінюються між різними програмами, написаними різними мовами і такими, що працюють у різних ОС. Кожна може очікувати своє кодування. Якщо не домовитися заздалегідь — отримаєте «кракозябри» і важковловимі баги. Типовий випадок: база даних зберігає текст у UTF-8, а програма читає вихідний файл як Windows-1251 і завантажує у БД — спотворені символи гарантовані.

9. Типові помилки під час роботи з кодуваннями

Помилка № 1: Не вказано кодування під час читання/запису файлу.
У результаті програма працює «в мене на комп’ютері», а в колеги — «кракозябри».

Помилка № 2: Використання застарілих конструкторів (FileReader, FileWriter).
Вони завжди використовують системне кодування — пастка для новачків.

Помилка № 3: Неправильне кодування файлу‑джерела.
Якщо файл було записано в одному кодуванні, а читається в іншому, частина символів буде спотворена або замінена на знаки питання.

Помилка № 4: Втрата символів під час переходу між кодуваннями.
Якщо цільове кодування не підтримує всі символи (наприклад, ASCII замість UTF-8), частина тексту просто зникне.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ