Netty的深入浅出--33.java字符集编码解码详解

对于字符集编码来说,很多人都不太理解,一直是一个老大难问题。

下面这个例子采用的是NIO流形式读取文件,不是IO流哦

下面先写一个例子,将一个文件拷贝到另外一个文件中:

目的是将NioTest13_In.txt文件内容拷贝到NioTest13_Out.txt中

Netty的深入浅出--33.java字符集编码解码详解

获取文件权限:

Netty的深入浅出--33.java字符集编码解码详解

 获取channel

Netty的深入浅出--33.java字符集编码解码详解

将input文件映射到ByteBuffer中

Netty的深入浅出--33.java字符集编码解码详解

接下来就是encode和decode,编码和解码,

encode编码就是将字符串编码成字节数组;

decode解码就是将字节数组解码成字符串。

设置字符集编码类型:

Netty的深入浅出--33.java字符集编码解码详解

获取到encode对象, decode对象

Netty的深入浅出--33.java字符集编码解码详解

将内存映射的bytebuffer解码成一个charBuffer

Netty的深入浅出--33.java字符集编码解码详解

将charBuffer编码成一个byteBuffer

Netty的深入浅出--33.java字符集编码解码详解

 写入到output文件中

Netty的深入浅出--33.java字符集编码解码详解

 运行程序

Netty的深入浅出--33.java字符集编码解码详解

Netty的深入浅出--33.java字符集编码解码详解

 Netty的深入浅出--33.java字符集编码解码详解

现在将字节码类型改成iso

Netty的深入浅出--33.java字符集编码解码详解

运行程序:

纳尼!结果没有出现乱码!而且输出文件编码格式还是utf-8,这是神马情况,是不是颠覆三观了╮(╯▽╰)╭

Netty的深入浅出--33.java字符集编码解码详解

为什么中文在iso-8859-1的情况下还能正常输出

大部分情况下iso编码类型情况下的中文都会出现乱码,而现在却是没有出现;

现在就出现一个矛盾,源文件是utf-8的编码格式,而解码器和编码器都是iso-8859-1,生成的文件竟然还是utf-8,暂时不要急着找答案,继续往下面看:

查看所有可用字符集:

Netty的深入浅出--33.java字符集编码解码详解

 我们先了解一下所有比较常用的字节码类型之间的关系

首先最早出现的ASCII码:

Netty的深入浅出--33.java字符集编码解码详解

1个ASCII码可以表示128个字符,因此对于西方国家来说已经完全够了 

Netty的深入浅出--33.java字符集编码解码详解

从美国和英国之后计算机传入到德国法国,发现ASCII码无法全部表达,所以就出现了iso-8895-1;

因为iso-8895-1是ASCII的一个扩展,它完全兼容ASCII码。

Netty的深入浅出--33.java字符集编码解码详解

但是问题又出现了,256个字符表示德国法国的字符是够的,而我们中国和朝鲜等国家的字符却远远不够

因此出现了由我们中国制定的gb2312

Netty的深入浅出--33.java字符集编码解码详解

 但是问题又来了,在指定gb2312的时候,没有考虑到很多生僻字,因此出现了gbk,不过后来又发现gbk对于少数汉字还是不能表示,接着有出现了gb18030;

这时候*自己也指定了一套编码规则:big5(因为他们是繁体中文,我们大陆是简单中文,写法不一样)

但是大问题来了,如果每个国家都指定一套自己的编码格式,那操作系统不就乱套了吗。这时候就出现了国际标准化组织,它将全球所以的语言全部集中起来,制定了unicod

但是问题又来了,unicode需要两个字节来表示一个字符,这样的话,对于英语使用的国家来说,表示一个字符只需要7bit(8bit等于1个字节),现在文件的存储量翻了两倍,对于存储量大的来说这翻的倍数是非常可怕的。

Netty的深入浅出--33.java字符集编码解码详解

 最后utf出现了

Netty的深入浅出--33.java字符集编码解码详解

Netty的深入浅出--33.java字符集编码解码详解

Netty的深入浅出--33.java字符集编码解码详解

 

现在我们 的问题又回到之前:

对于iso-8895-1存储数据的时候,按照8bit(一个字节)来存储一个字符

在utf-8中英文都是用一个字节来存储的,汉字是三个字节:

现在“你好”这两个汉字解码之后成为6个字节,这个时候肯定是乱码的。

Netty的深入浅出--33.java字符集编码解码详解

如果是12的话,实际上获取的是第一个汉字“你”的第一个字节

Netty的深入浅出--33.java字符集编码解码详解

所以说运行之后就产生了一个乱码:

Netty的深入浅出--33.java字符集编码解码详解

我假设的是“你好”的ASCII码是下面六个字节,可以直观的打印出来 

Netty的深入浅出--33.java字符集编码解码详解

所以现在,你应该就能理解了,当如果你的汉字个数不是偶数的话,你通过iso编码和解码之后肯定乱码,至于为什么自己多想想咯^_^