CodeGym /Kurslar /JAVA 25 SELF /Kodirovkalar uyğunsuzluğu problemləri, tipik səhvlər

Kodirovkalar uyğunsuzluğu problemləri, tipik səhvlər

JAVA 25 SELF
Səviyyə, Dərs
Mövcuddur

1. Səhvlərin simptomları

İdeal dünyada proqramçılar faylın hansı kodirovkada yazıldığını həmişə bilirlər və onu oxuyarkən düzgün göstərirlər. Amma reallıq — bu, faylların Windows, Linux, serverlər, redaktorlar arasında “gəzdiyi” və hər birinin baytları öz qaydasına görə yozduğu bir dünyadır. Nəticədə belə simptomlarla rastlaşırıq:

  • “Mojibake” — gözlənilən mətn əvəzinə qəribə simvollar, sual işarələri, kvadratlar və ya heç bir dilə bənzəməyən hərf yığını görünür.
  • Simvolların itməsi — mətnin bir hissəsi yox olur və ya ? ilə əvəzlənir.
  • İstisnalar — məsələn, Java seçilmiş kodirovkada baytları “həzm” edə bilməyəndə MalformedInputException.
  • Parsinq zamanı səhvlər — proqram faylı düzgün emal edə bilmir, çünki əsas açar sözlər və ya strukturlar mətnin təhrifinə görə zədələnir.

Bu, kiril hərfləri olan faylın səhv kodirovka ilə oxunması zamanı yaranan “mojibake” üçün klassik nümunədir:

Gözlənilən:  Salam, dünya!
Alınan: Привет, мир

Bu, yeni bir dil deyil, sadəcə baytların lazım olan “lüğət”lə deyil, başqa cür yozulmasının nəticəsidir.

2. Səhvlər niyə yaranır: problemin kökü

Fayl bir kodirovkada yazılıb, başqa kodirovkada oxunur

Tutaq ki, kimsə faylı Windows-1251-də saxlayıb, siz isə onu UTF-8-də açırsınız. Java baytları UTF-8 qaydalarına görə dürüstcə deşifrə etməyə çalışır, amma mənasızlıq alınır, çünki bayt dəyərləri gözlənilənlərlə üst-üstə düşmür.

Sistem kodirovkasından “susmaya görə” istifadə

Kodirovkanı açıq göstərməsəniz, Java sistem kodirovkasından — yəni kompüterinizdə qurulmuş olandan — istifadə edir. Rus lokalı olan Windows-da bu Windows-1251 ola bilər, Linux-da — UTF-8, Mac-də — yenə UTF-8. Sizdə əla açılan fayl, başqa OS ilə işləyən həmkarınızda oxunmaz ola bilər.

Köhnəlmiş konstruktorlardan istifadə

Köhnə Java versiyalarında (və bəzi dərsliklərdə) tez-tez FileReader/FileWriter kimi konstruksiyalarla rastlaşırıq; bunlar sistem kodirovkasından istifadə edir və sizə nəzarət imkanı vermir — bu isə tələ və “mojibake” mənbəyidir.

FileReader reader = new FileReader("file.txt");
FileWriter writer = new FileWriter("file.txt");

BOM-un (Byte Order Mark) olması və ya olmaması

Bəzi kodirovkalar (məsələn, UTF-8 BOM ilə və ya UTF-16) faylın əvvəlində öz mahiyyətini bildirmək üçün xüsusi baytlar əlavə edir. Proqram BOM gözləmirsə və ya əksinə — onu gözləyir, amma tapmırsa, problemlər yarana bilər: ya faylın ilk simvolları təhrif olunur, ya da fayl ümumiyyətlə tanınmır.

3. Səhvlər necə təzahür edir: praktik baxış

Nümunə 1: Kiril hərfləri olan fayl Windows-1251-də yazılıb, UTF-8 kimi oxunur

import java.nio.file.*;
import java.nio.charset.*;

public class EncodingDemo {
    public static void main(String[] args) throws Exception {
        Path path = Paths.get("russian.txt");
        // Fayl Windows-1251-də yazılıb, UTF-8 kimi oxunur — nəticə mojibake olacaq!
        try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
            System.out.println(reader.readLine());
        }
    }
}

Nəticədə “Salam, dünya!” əvəzinə qəribə simvollar görəcəksiniz.

Nümunə 2: Fayl UTF-8-də yazılıb, ISO-8859-1 kimi oxunur

try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.ISO_8859_1)) {
    System.out.println(reader.readLine());
}

Nəticə: Bütün ASCII-olmayan simvollar zibilə çevriləcək və ya ? ilə əvəz olunacaq.

Nümunə 3: Faylı oxuyarkən istisna

Əgər baytlar seçilmiş kodirovkanın qaydalarına uyğun deyilsə, Java istisna ata bilər:

Exception in thread "main" java.nio.charset.MalformedInputException: Input length = 1
    at java.base/sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
    ...

Bu o deməkdir ki, Java seçilmiş kodirovkada düzgün şərh edilə bilməyən bayta rast gəlib.

4. Diaqnostika: kodirovkada nəyin səhv olduğunu necə anlamaq

Faylın kodirovkasını yoxlayın

  • Notepad++, VS Code və ya Sublime Text kimi redaktorlarda adətən faylın kodirovkasına baxmaq və ya onu dəyişmək olur (adətən alt paneldə).
  • Linux-da komanda ilə kodirovka barədə (hər zaman 100% dəqiq olmasa da) ipucu almaq olar:
file fayl_adi.txt

Java-nın sistem kodirovkasını yoxlayın

Konsola file.encoding xüsusiyyətinin dəyərini çıxarın:

System.out.println(System.getProperty("file.encoding"));

Test məlumatlarından istifadə edin

Müxtəlif simvollardan (kiril, latın, xüsusi simvollar, emoji) ibarət kiçik bir fayl yaradın, onu müxtəlif kodirovkalarda oxumağa çalışın və nəticənin gözləntilərinizlə nə vaxt üst-üstə düşdüyünə baxın.

Həmişə kodirovkanı açıq şəkildə göstərin

Kodda faylın oxunması/yazılması kodirovka göstərilmədən aparılırsa — bu, şübhələnmək üçün səbəbdir. Məsələn, “susmaya görə” seçimlər əvəzinə Files.newBufferedReader(..., StandardCharsets.UTF_8) istifadə edin.

5. Best practices: tələyə düşməmək üçün

Qayda №1:
HƏMİŞƏ fayllarla işləyərkən kodirovkanı açıq şəkildə göstərin, xüsusən fayl müxtəlif kompüterlərdə, müxtəlif OS-lərdə istifadə olunacaqsa və ya şəbəkə üzərindən göndəriləcəksə.

Qayda №2:
Müasir, “anlaşılan” kodirovkalardan istifadə edin — ilk növbədə UTF-8 (StandardCharsets.UTF_8). Yalnız xüsusi tələblər olduqda (məsələn, köhnə sistemlə inteqrasiya) digər kodirovkalardan istifadə edin.

Qayda №3:
FileReader və FileWriter siniflərindən uzaq durun (onlar kodirovkanı göstərməyə imkan vermir), onların əvəzinə InputStreamReader, OutputStreamWriter və ya Files metodlarını açıq Charset ilə istifadə edin.

Qayda №4:
Nəticəni yoxlayın! Yazdığınız faylları müxtəlif kodirovkaları dəstəkləyən redaktorlarda açın ki, mətnin düzgün göründüyünə əmin olasınız.

6. Xüsusiyyətlər və nüanslar: BOM, XML, JSON və digər “maraqlı” hallar

BOM (Byte Order Mark): bəzən UTF-8-dəki fayl “görünməyən” baytlarla (EF BB BF) başlayır. Müasir proqramların çoxu bunları yox sayır, amma bəziləri sətrin əvvəlində “mojibake” göstərə və ya faylı qəbul etməyə bilər (məsələn, köhnə XML/JSON parsərləri).

XML/HTML: bəzən faylın əvvəlində <?xml version="1.0" encoding="UTF-8"?> kimi sətir olur. Bu, proqrama baytların hansı kodirovkada gözlənildiyini bildirir. Amma faktiki kodirovka elan olunandan fərqlidirsə — yenə “mojibake”.

JSON: standart üzrə UTF-8 olmalıdır, amma fayl Windows-1251-də yaradılıbsa, parsər ya səhv verəcək, ya da təhrif olunmuş məlumat qaytaracaq.

1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Qədim pergamenti səhv linza ilə deşifr etməyə cəhd 🔎
Qədim pergamenti səhv linza ilə deşifr etməyə cəhd 🔎
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Tərcüməçilərin müqayisəli analizi: Mətndə məna necə dəyişir 🌍
Tərcüməçilərin müqayisəli analizi: Mətndə məna necə dəyişir 🌍
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION