Rešavanje problema sa kineskim poremećajem znakova: Kompletni vodič kroz kodiranje znakova — ASCII, Unicode, UTF-8, GB2312 detaljno
Samo juče, videla sam u Ergeovoj programerskoj planeti ovakvu snimku ekrana, jedan prijatelj se žalio da se na stranici Alipay finansiranja pojavio kineski poremećaj znakova, mislim da mnogi prijatelji kao i ja ostali šokirani😮! Ali i velike kompanije kao Ali mogu napraviti ovakvu osnovnu grešku?

Da li je jučnji ljudski resurs uložen u iznenadno objavljivanje „Tongyi Qianwen"?
Uz ovu priliku, pogledajmo kako nastaju kineski poremećaji i kako brzo rešiti problem poremećaja.
Šta je kineski poremećaj znakova
P: Šta je kineski poremećaj znakova?
GPT4: Kineski poremećaj znakova se odnosi na pojavu u kompjuterskom sistemu ili softveru gde se, zbog neusklađenosti ili nepravilnog tretiranja kodiranja znakova, kineski znakovi ne mogu normalno prikazati, dolazi do pojave poremećaja. Ova pojava se obično manifestuje time da se kineski znakovi zamenjuju drugim nevezanim znakovima, simbolima ili poremećajima.
Na primer, istorijski poznati "KÅ«n jÄ«n kÇo" je savršen predstavnik kineskih poremećaja.

Šta je kodiranje znakova
P: Šta je kodiranje znakova?
GPT4: Kodiranje znakova (Character Encoding) je pravilo ili sporazum koji mapira znakove (kao što su slova, brojevi, interpunkciski znakovi itd.) u binarne podatke u kompjuteru. Jednostavno rečeno, kodiranje znakova je proces pretvaranja znakova čitljivih ljudima u binarne podatke koje kompjuter može obraditi.
Za kompjuter, prepoznaje samo 0 i 1, sve informacije su na kraju binarni broj. Jedan binarni broj je ili 0 ili 1. Osam binarnih brojeva zajedno čine jedan bajt, kombinovaće 256 stanja, to je 2 na 8 stepen (2^8), od 00000000 do 11111111.
Da bi kompjuter mogao prepoznati i obraditi različite znakove, potrebno je koristiti kodiranje znakova za kodiranje i dekodiranje znakova. Uobičajena kodiranja znakova uključuju ASCII, UTF-8, UTF-16, GBK, GB2312 itd.

1) ASCII
ASCII kod se razvio iz telegrafskog koda, prvo izdanje standarda objavljeno je 1963. godine, poslednje ažuriranje bilo je 1986. godine, do sada ukupno definisano 128 znakova. Od toga 33 znakova se ne mogu prikazati na oprezi za opštu upotrebu, potrebna je specijalna oprema za prikaz.
Ograničenje ASCII koda je u tome što može prikazati samo 26 osnovnih latiničnih slova, arapske brojeve i engleske interpunkcijske znakove, stoga se može koristiti samo za prikaz modernog američkog engleskog, za druge jezike nemoćan, na primer u francuskom, slova imaju akcente, ne može se predstaviti ASCII kodom.

PS: Latinična slova (takođe poznata kao rimska slova) su sistem slova koji koristi većina evropskih jezika, najkorišćeniji sistem slovnih pisama na svetu, jedno od dostignuća rimske civilizacije.
Iako se u imenu zovu latinična slova, latinski jezik ne koristi J, U i W ova tri slova.
U mom utisku, možda reći latinična slova deluje malo strano, reći engleska slova možda ima intuitivan utisak.

Arapski brojevi, vrlo smo poznati.

Ali arapski brojevi nisu potekli iz Arabije, već iz stare Indije. Ako ste učili istoriju, trebalo bi da imate neki utisak, Arabija se nalazi u zapadnoj Aziji i severnoj Africi, arapski jezik kao glavni jezik, islam kao glavna vera.

Na takvoj geografskoj lokaciji, poslovanje između istočne Azije i Evrope je vrlo prednost, stoga su arapski brojevi Arapi preneli u Evropu, otuda i ime.
Engleski interpunkcijski znakovi, takođe poznati kao engleski znakovi interpunkcije, slični su kineskim interpunkcijskim znacima. Interpunkcijski znakovi su pomoćni znakovi za zapisivanje jezika, sastavni deo pisanog jezika, služe za označavanje pauze, pojačavanja tona itd.
Engleski interpunkcijski znakovi su se u 16. veku podelili na školu recitacije i gramatičku školu, glavno evoluirali iz klasičnog grčkog i latinskog jezika, posle 17. veka ušli su u stabilnu fazu. Ruski interpunkcijski znakovi potiču iz grčkog, posle 18. veka takođe su usvojili engleske interpunkcijske znakove.
Kod mnogih ljudi, starinski tekst nema interpunkcijske znakove, ali doktor Guan Xihua istražuje i ukazuje, Kina je još u periodu pre-Qin imala interpunkcijske znakove, kasnije se stopila sa nekim engleskim interpunkcijskim znacima, postepeno formirajući današnje kineske interpunkcijske znakove.

2) Unicode
Na svetu sem engleskog, postoje još francuski, portugalski, španski, nemački, ruski, arapski, korejski, japanski itd. ASCII kod je više nego dovoljan za predstavljanje engleskog, ali ovi drugi jezici ne mogu.
Kao maternji jezik mog gospodara Ergea — kineski, vrlo je dubok i obiman, odgovarajući broj kineskih znakova je vrlo velik. „Shuowen Jiezi“ iz dinastije Han sadrži 9353 znaka, „Kangxi Dictionary“ iz dinastije Qing sadrži 47035 znakova, savremeni „Veliki kineski rečnik“ sadrži 60370 znakova. 1994. godine Zhonghua Book Company i China Friendship Publishing Company objavili su „Zhonghua Zihai“ sa 85568 znakova.
Uobičajenih znakova ima oko 2500, manje uobičajenih 1000.
Jedan bajt može predstaviti samo 256 simbola, stoga ako se ASCII kod koristi za predstavljanje kineskih znakova, daleko je nedovoljno, potrebno je koristiti više bajtova. Uobičajeni način kodiranja pojednostavljenog kineskog je GB2312, koristi dva bajta za predstavljanje jednog kineskog znaka, teorijski može predstaviti najviše 256 x 256 = 65536 simbola.
Treba znati da na svetu postoji više načina kodiranja, isti binarni broj može se protumačiti kao različiti znakovi. Stoga, za otvaranje tekstualne datoteke, morate znati njeno kodiranje, inače će se koristeći pogrešno kodiranje za tumačenje pojaviti poremećaj.
- Kodiranje je pretvaranje originalnih podataka (na primer teksta, slike, videa, audija itd.) u binarni oblik.
- Dekodiranje je pretvaranje binarnih podataka u originalne podatke, to je obrnuti proces.
Ako postoji kodiranje koje uključuje sve simbole sveta. Svaki simbol dodeljuje se jedinstveni kod, problem poremećaja će se potpuno nestati.
Ko će obaviti ovaj težak zadatak? Unicode, kineski prevod je Unikod, međunarodni kod, objedinjeni kod, jedinstveni kod, baš kao što mu i ime kaže, ovo je kodiranje svih simbola.
Unicode se do danas stalno dopunjuje, svako novo izdanje dodaje nove znakove. Trenutno najnovija verzija je 13.0 objavljena marta 2020. godine, sadrži 130 hiljada znakova.

Unicode je veliki skup, trenutna veličina može sadržati preko milion simbola. Kod svakog simbola je različit, na primer, U+0639 predstavlja arapsko slovo Ain, U+0041 predstavlja englesko veliko slovo A, U+4E25 predstavlja kineski znak.
Specifičnu tabelu odgovora znakova možete potražiti:
- unicode.org:http://www.unicode.org
- Tabela kineskih znakova:ttp://www.chi2ko.com/tool/CJK.htm
Neki su tako rekli:
Unicode podržava gornju granicu od 65536 znakova, Unicode znakovi moraju zauzimati dva bajta.
Ali to je zabluda, zapamtite, Unicode je samo standard za mapiranje znakova i brojeva. Nema ograničenja broja znakova koje podržava, ne zahteva da znak mora zauzeti dva, tri ili bilo koji drugi broj bajtova, stoga može biti beskonačan.
3) UTF-8
Iako je Unicode objedinio kodiranje znakova celog sveta, nije propisao kako se skladišti. Ako se propisano, svaki simbol treba predstaviti sa 3 ili 4 bajta, zato što 2 bajta mogu predstaviti samo 65536, uopšte ne može predstaviti sve.
Šta raditi?
UTF (Unicode Transformation Formats, načini kodiranja Unicode) dolazi! Najčešći su UTF-8 i UTF-16.
U UTF-8, znakovi 0-127 se predstavljaju sa 1 bajtom, koristeći isto kodiranje kao ASCII. Samo znakovi 128 i više se predstavljaju sa 2, 3 ili 4 bajta.
Ako postoji samo jedan bajt, najviši bit je 0; ako postoji više bajtova, prvi bajt počev od najvišeg bita, koliko uzastopnih bitova ima vrednost 1, toliko bajtova se koristi za kodiranje, preostali bajtovi sve počinju sa 10.
Specifični oblik je:
- 0xxxxxxx: jedan bajt;
- 110xxxxx 10xxxxxx: oblik kodiranja sa dva bajta (početak sa dve 1);
- 1110xxxx 10xxxxxx 10xxxxxx: oblik kodiranja sa tri bajta (početak sa tri 1);
- 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx: oblik kodiranja sa četiri bajta (početak sa četiri 1).
To znači, UTF-8 je način kodiranja promenljive dužine — ovo je njegova prednost ali i mane.
Kako to kažu? Prednost je u tome što obuhvata sve, mana je u gubljenju prostora. Na primer, UTF-8 koristi 3 bajta (256*256*256=16777216) za kodiranje uobičajenih kineskih znakova, ali uobičajenih kineskih znakova nema toliko, za kompjuter je to ozbiljno gubljenje resursa.
4) GB2312
S obzirom na to, Kineska nacionalna uprava za standarde je 1980. godine objavila kodiranje GB2312, to jest nacionalni standard KNR za skup pojednostavljenih kineskih znakova. GB2312 standard sadrži ukupno 6763 kineska znaka (dva bajta su dovoljna), od toga 3755 znakova prvog nivoa, 3008 znakova drugog nivoa; ujedno sadrži 682 znaka uključujući latinična slova, grčka slova, japanska hiragana i katakana slova, ruska ćirilička slova.
Pojavom GB2312, u osnovi je zadovoljena potreba kompjuterske obrade kineskih znakova. Za retke znakove i tradicionalne znakove koji se pojavljuju u imenima ljudi, starom kineskom jeziku itd., GB2312 ne može da obradi, stoga je nastao GBK (K je prvi glas fonetskog pinjina „proširenje“ (kuòzhǎn)).
Kako nastaju kineski poremećaji?
P: Dajte primer kineskih poremećaja, kineski je Chenmo Wang Er
GPT4: Ispod je primer koji može dovesti do kineskih poremećaja. Prvo koristeći GBK kodiranje pretvaramo kineski niz znakova „Chenmo Wang Er“ u niz bajtova, zatim koristeći UTF-8 kodiranje pretvaramo niz bajtova natrag u niz znakova. To će dovesti do pojave poremećaja pri dekodiranju niza.
public class EncodingDemo {
public static void main(String[] args) {
String originalStr = "Chenmo Wang Er";
String encodedStr = "";
try {
byte[] bytes = originalStr.getBytes("GBK");
encodedStr = new String(bytes, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.out.println("Pre konverzije: " + originalStr);
System.out.println("Posle konverzije: " + encodedStr);
}
}Šta će program ispisati?
Pre konverzije: Chenmo Wang Er
Posle konverzije: ��Ĭ����Hehe, poremećaj je došao! U Unicode-u, � je specijalan simbol, koristi se za predstavljanje onog što se ne može prikazati, njegov heksadecimalni broj je 0xEF 0xBF 0xBD. Tada dva � su 0xEF 0xBF 0xBD 0xEF 0xBF 0xBD, ako se dekodira koristeći GBK, to je poznati „KÅ«n jÄ«n kÇo“.
Može se proveriti kroz kod:
// Ispis efbfbdefbfbd
char[] kuijinkao = HexUtil.encodeHex("��", StandardCharsets.UTF_8);
System.out.println(kuijinkao);
// Pomoću hutool pretvaramo u binarni
byte[] testBytes = HexUtil.decodeHex(kuijinkao);
// Koristeći GBK dekodiranje
String testResult = new String(testBytes, Charset.forName("GBK"));
// Ispis KÅ«n jÄ«n kÇo (mojibake primer)
System.out.println(testResult);Pogledaj rezultate:
efbfbdefbfbd
KÅ«n jÄ«n kÇoStoga, ubuduće kada vidite KÅ«n jÄ«n kÇo, prvo mislite na problem konverzije UTF-8 i GBK, tačno.
Kako rešiti kineski poremećaje?
P: Kako rešiti kineski poremećaje?
GPT4: Rešavanje problema kineskih poremećaja zahteva osiguravanje istog kodiranja znakova pri kodiranju i dekodiranju. Ovo je izmenjen primer koji pokazuje kako izbeći kineske poremećaje:
String originalStr = "Chenmo Wang Er";
byte[] bytes = originalStr.getBytes(StandardCharsets.UTF_8);
String encodedStr = new String(bytes, StandardCharsets.UTF_8);
System.out.println("Pre ispravne konverzije: " + originalStr);
System.out.println("Posle ispravne konverzije: " + encodedStr);Rezultat:
Pre ispravne konverzije: Chenmo Wang Er
Posle ispravne konverzije: Chenmo Wang ErPored toga, evo nekoliko praksi za izbegavanje poremećaja:
- Koristiti jedinstveno kodiranje znakova, kao što je UTF-8. Sadržai sve Unicode znakove, i široko je podržano. Osigurajte da se na svim platformama i sistemima koristi isto kodiranje.
- Pri radu sa tekstualnim datotekama, uvek eksplicitno navedite kodiranje znakova. Na primer, u Javi kada koristite InputStreamReader, OutputStreamWriter, navedite parametar kodiranja.
- U HTML, XML i drugim dokumentima, navedite kodiranje znakova. Na primer, u HTML stranici dodajte
<meta charset="UTF-8">. - Za baze podataka, osigurajte korišćenje ispravnog skupa znakova. Pri kreiranju baze podataka i tabela, eksplicitno navedite skup znakova, kao što je utf8mb4.
Pri komunikaciji sa trećim stranama, osigurajte da obe strane koriste isto kodiranje znakova. Pri obradi API zahteva i odgovora, proverite da li se kodiranje znakova poklapa.
P: Za takve proizvodne nesreće kao Alipay, kako brzo locirati i rešiti problem?
GPT4:
Prikupljanje informacija: Razumite specifičan manifestaciju problema, na primer koje stranice ili funkcije su pogođene, ozbiljnost problema, i povratne informacije korisnika. Ovo će pomoći brzom lociranju obima problema.
Provera dnevnika: Pregledajte dnevnik servera i dnevnik aplikacija, proverite da li postoje abnormalne informacije ili greške. Informacije iz dnevnika pomažu u identifikaciji vremena i konkretnog uzroka problema.
Reprodukcija problema: Pokušajte da reprodukujete problem u testnom okruženju kako biste dublje razumeli detalje problema. Ako se problem ne može reprodukovati, možda će trebati dalje prikupiti detaljne informacije iz proizvodnog okruženja.
Lociranje problema: Na osnovu prikupljenih informacija, odredite deo koda ili sistema gde se problem može dogoditi. Proverite odgovarajući kod, posebno delove koji se tiču kodiranja znakova, prenosa podataka, operacija baze podataka.
Rešavanje problema: Popravite problematični kod, osigurajte da kodiranje znakova ostaje konzistentno u celom sistemu. Sprovedite jedinična testiranja i integraciona testiranja, potvrdite da je problem rešen.
Deployovanje popravke: Deploy-ujte popravljenu kod u proizvodnju. Da biste izbegli uticaj na normalni servis, možete razmisliti o verifikaciji u manjem proizvodnom okruženju, zatim postepeno proširiti opseg deploy-a.
Monitoring: Nakon popravke nastavite pratiti stanje rada sistema, osigurajte da je problem rešen. Prikupite povratne informacije korisnika, potvrdite zadovoljstvo korisnika.
Sumiranje iskustva: Za ovaj problem, sumirajte iskustva i lekcije, analizirajte korenne uzroke problema, optimizujte proces razvoja i testiranja, izbegavajte slične probleme u budućnosti.
