关于java中编码的一些小细节

来源:互联网 发布:mysql 不等于空 编辑:程序博客网 时间:2024/05/17 08:20

1.平台默认编码

   所谓平台默认编码并不是指你的操作系统的默认编码方式,而是你当前这个类文件所采用的编码方式!同一个包下的不同类采用不同的编码方式那么你在使用String中的getBytes方法时所得到的字节数组都是不一样的.
   例如我有两个类:TestA和TestB,第一个使用GBK编码,第二个使用UTF-8编码,那么这两个类在执行同样的代码时却由不同的输出.

String str = "可乐喝咖啡";byte[] bt = strB.getBytes();System.out.println(bt.length);

此段代码在使用GBK编码的类中运行时会打印:10

但代码在使用UTF-8编码的类中运行时会打印:15

所以在涉及编码问题时这些小细节还是值得注意的.

2.windows记事本的编码方式

作者:Keen Kwok
链接:https://www.zhihu.com/question/41426907/answer/90924168

来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

   Windows早期(至少是95年以前的事情了)是ANSI字符集的,也就是说一个中文文本在Windows简体中文版显示的是中文,到Windows日文版显示的就不知道是什么东西了。后来,Windows支持了Unicode,但当时大部分软件都是用ANSI编码的,unicode还不流行,怎么办?Windows想了个办法,就是允许一个默认语言编码,就是当遇到一个字符串,不是unicode的时候,就用默认语言编码解释。(在区域和语言选项里可以改默认语言)这个默认语言,在不同Windows语言版本里是不同的,在简体中文版里,是GBK,在繁体中文版里,是BIG5,在日文版里是JIS而记事本的ANSI编码,就是这种默认编码,所以,一个中文文本,用ANSI编码保存,在中文版里编码是GBK模式保存的时候,到繁体中文版里,用BIG5读取,就全乱套了。记事本也不甘心这样,所以它要支持Unicode,但是有一个问题,一段二进制编码,如何确定它是GBK还是BIG5还是UTF-16/UTF-8?记事本的做法是在TXT文件的最前面保存一个标签,如果记事本打开一个TXT,发现这个标签,就说明是unicode。标签叫BOM,如果是0xFF 0xFE,是UTF16LE,如果是0xFE 0xFF则UTF16BE,如果是0xEF 0xBB 0xBF,则是UTF-8。如果没有这三个东西,那么就是ANSI,使用操作系统的默认语言编码来解释。Unicode的好处就是,不论你的TXT放到什么语言版本的Windows上,都能正常显示。而ANSI编码则不能。(UTF-8的好处是在网络环境下,比较节约流量,毕竟网络里英文的数据还是最多的)

测试代码

RandomAccessFile raf = new RandomAccessFile("src.txt","rw");raf.write("咖啡喝可乐".getBytes("UTF-8"));raf.close();RandomAccessFile raf1 = new RandomAccessFile("tar.txt","rw");raf1.write("咖啡喝可乐".getBytes("GBK"));raf1.close();

结果:都两个记事本会正确显示”咖啡喝可乐”

与预期的一致,记事本并没有直接按照系统默认的GBK方式解码

细节:如果先调用了raf.writeDouble(45);再调用raf.write("咖啡喝可乐".getBytes("UTF-8"));
那么会出现乱码.原因很简单,第一个方法写入一个与平台无关的double值.在记事本中肯定是以乱码的形式出现,关键是它的出现导致记事本没有找到BOM,所以使用了GBK解码,从而无法解析UTF-8的”可乐喝咖啡”!

原创粉丝点击