“嗨,阿米戈!”

“现在是时候讨论另一个有趣的话题了:编码。”

“也许你已经在某处听说过,每个字符都有一个代码(数字)。这就是为什么 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。”