“嗨,阿米戈!”

“現在是時候討論另一個有趣的話題了:編碼。”

“也許你已經在某處聽說過,每個字符都有一個代碼(數字)。這就是為什麼 char 類型可以同時表示符號和數字的原因。”

》比如英文字母‘A’的編碼是65,‘B’是66,‘C’是67,等等。大寫字母、小寫字母、西里爾字母、中文都有唯一的編碼字符(是的,很多很多代碼)、數字和各種符號。簡而言之,幾乎所有你稱之為字符的東西都有一個代碼。”

“那麼,每個字母和字符都對應著某個數字?”

“恰恰。”

“字符可以轉換為數字,數字可以轉換為字符。Java 通常看不出它們之間的區別:”

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

“有趣的。”

“因此,編碼是一組符號及其對應的一組代碼。但不僅發明了一種編碼——還有相當多的編碼。直到後來才發明了一種通用的通用編碼 Unicode。”

“但無論發明了多少通用標準,沒有人急於放棄舊標準。然後一切都像這部卡通片一樣發生:”

字符編碼 - 1

“想像一下,文森特和尼克決定製作他們自己的編碼。”

“這是文森特的編碼:”
字符編碼 - 2

“這是尼克的編碼:”
字符編碼 - 3

“他們甚至使用相同的字符,但字符的代碼不同。”

“當使用 Vincent 編碼將字符串‘ABC-123’寫入文件時,我們得到以下字節集:”
字符編碼 - 4

“現在另一個使用 Nick 編碼的程序想要讀取文件:”

“這是它的內容:«345-IJK»。”

“最糟糕的是,編碼通常不會存儲在文件中的任何位置,因此開發人員不得不猜測。”

“嗯,他們怎麼猜的?”

“那是一個不同的話題。但我想解釋一下如何使用編碼。正如您已經知道的那樣,Java 中 char 的大小是兩個字節。Java 字符串使用 Unicode 格式。”

“但是 Java 允許您將 String 轉換為它所知道的任何編碼的一組字節。String 類對此有特殊的方法。Java 也有一個特殊的 Charset 類來描述特定的編碼。”

1) 如何獲得 Java 支持的所有編碼列表?

“為此有一個名為 availableCharsets 的特殊靜態方法。“此方法返回一組對(編碼名稱,描述編碼的對象):”

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

“每種編碼都有一個唯一的名稱。以下是其中的一些名稱:UTF-8、UTF-16、Windows-1251、KOI8-R,……”

2) 如何獲得當前的活動編碼 (Unicode)?

“為此有一個名為defaultCharset的特殊方法。

Charset currentCharset = Charset.defaultCharset();

3) 如何將字符串轉換為特定的編碼?

“在 Java 中,您可以使用 Java 知道的任何編碼將字符串轉換為字節數組:”

方法 例子
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) 如果我知道文件中的編碼是什麼,如何將從文件讀取的字節數組轉換為字符串?

“這更容易。String 類有一個特殊的構造函數:”

方法 例子
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) 如何將字節數組從一種編碼轉換為另一種編碼?

“有很多方法。這是最簡單的一種:”

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);

“我就是這麼想的。謝謝你的有趣教訓,Rishi。”