"Cześć, Amigo!"

„Teraz czas na kolejny interesujący temat: kodowanie”.

„Być może już gdzieś słyszałeś, że każdy znak ma kod (liczbę). Dlatego typ znaku może reprezentować zarówno symbole, jak i liczby”.

Na przykład kod dla litery „A” w alfabecie angielskim to 65. „B” to 66, „C” to 67 itd. Istnieją unikalne kody dla wielkich i małych liter, cyrylicy, chińskiego znaki (tak, mnóstwo kodów), cyfry i różne symbole. Krótko mówiąc, istnieje kod dla praktycznie wszystkiego, co można nazwać postacią ”.

„Więc każda litera i znak odpowiada jakiejś liczbie?”

"Dokładnie."

„Znak można przekonwertować na liczbę, a liczbę na znak. Java generalnie nie widzi między nimi różnicy:”

char c = 'A'; //The code (number) for 'A' is 65
c++; //Now c contains the number 66, which is the code for 'B'

"Ciekawy."

„Tak więc kodowanie to zestaw symboli i odpowiadający im zestaw kodów. Ale nie wynaleziono tylko jednego kodowania — jest ich całkiem sporo. Dopiero później wynaleziono powszechne uniwersalne kodowanie, Unicode”.

„Ale bez względu na to, ile wymyślono uniwersalnych standardów, nikomu nie spieszy się z porzuceniem starych. A potem wszystko dzieje się tak, jak w tej kreskówce:”

Kodowanie znaków - 1

„Wyobraź sobie, że Vincent i Nick postanawiają stworzyć własne kodowanie”.

„Oto kodowanie Vincenta:”
Kodowanie znaków - 2

„A oto kodowanie Nicka:”
Kodowanie znaków - 3

„Używają nawet tych samych znaków, ale kody znaków są różne”.

„Kiedy ciąg„ ABC-123 ”jest zapisywany do pliku przy użyciu kodowania Vincenta, otrzymujemy następujący zestaw bajtów:”
Kodowanie znaków - 4

„A teraz inny program, który używa kodowania Nicka, chce odczytać plik:”

„Oto, co przeczyta: «345-IJK»”.

„Najgorsze jest to, że kodowania zazwyczaj nie są przechowywane nigdzie w plikach, więc programiści muszą zgadywać”.

— No, jak oni je zgadują?

„To inny temat. Ale chcę wyjaśnić, jak pracować z kodowaniem. Jak już wiesz, rozmiar znaku w Javie to dwa bajty. A łańcuchy Java używają formatu Unicode”.

„Jednak Java umożliwia konwersję ciągu znaków na zestaw bajtów w dowolnym kodowaniu, jakie zna. Klasa String ma do tego specjalne metody. Java ma również specjalną klasę Charset, która opisuje określone kodowanie”.

1) Jak uzyskać listę wszystkich kodowań obsługiwanych przez język Java?

„Istnieje do tego specjalna metoda statyczna o nazwie availableCharsets. „Ta metoda zwraca zestaw par (nazwa kodowania, obiekt opisujący kodowanie):”

SortedMap<String,Charset> charsets = Charset.availableCharsets();

„Każde kodowanie ma unikalną nazwę. Oto niektóre z nich: UTF-8, UTF-16, Windows-1251, KOI8-R,…”

2) Jak uzyskać bieżące aktywne kodowanie (Unicode)?

„Istnieje do tego specjalna metoda o nazwie defaultCharset .

Charset currentCharset = Charset.defaultCharset();

3) Jak przekonwertować ciąg znaków na określone kodowanie?

„W Javie możesz przekonwertować ciąg znaków na tablicę bajtów w dowolnym kodowaniu znanym Javie:”

metoda Przykład
byte[] getBytes()
String s = "Good news, everyone!";
byte[] buffer = s.getBytes()
byte[] getBytes(Charset charset)
String s = "Good news, everyone!";
Charset koi8 = Charset.forName("KOI8-R");
byte[] buffer = s.getBytes(koi8);
byte[] getBytes(String charsetName)
String s = "Good news, everyone!";
byte[] buffer = s.getBytes("Windows-1251")

4) Jak przekonwertować tablicę bajtów, którą odczytuję z pliku na ciąg znaków, jeśli wiem, jakie było jego kodowanie w pliku?

„To jeszcze łatwiejsze. Klasa String ma specjalnego konstruktora:”

metoda Przykład
String(byte bytes[])
byte[] buffer = new byte[1000];
inputStream.read(buffer);

String s = new String(buffer);
String(byte bytes[], Charset charset)
byte[] buffer = new byte[1000];
inputStream.read(buffer);

Charset koi8 = Charset.forName("KOI8-R");
String s = new String(buffer, koi8);
String(byte bytes[], String charsetName)
byte[] buffer = new byte[1000];
inputStream.read(buffer);

String s = new String(buffer, "Windows-1251");

5) Jak przekonwertować tablicę bajtów z jednego kodowania na inne?

„Istnieje wiele sposobów. Oto jeden z najprostszych:”

Charset koi8 = Charset.forName("KOI8-R");
Charset windows1251 = Charset.forName("Windows-1251");

byte[] buffer = new byte[1000];
inputStream.read(buffer);
String s = new String(buffer, koi8);
buffer = s.getBytes(windows1251);
outputStream.write(buffer);

„Tak właśnie myślałem. Dzięki za interesującą lekcję, Rishi”.