Java与编码问题串讲之二–如何理解java采用Unicode编码
Java开发者必须牢记:在Java中字符仅以一种形式存在,那就是Unicode(不选择任何特定的编码,直接使用他们在字符集中的编号,这是统一的唯一方法)。由于java采用unicode编码,char 在java中占2个字节。2个字节(16位)来表示一个字符。
这里的Java中是指在JVM中、在内存中、在代码里声明的每一个char、String类型的变量中。
例如:
1
2
3
4
5
6
7
|
System.out.println(System.getProperty("file.encoding"));
char han = '永';
System.out.format("%x", (short)han);//对第二个参数(短整型)格式化为十六进制输出,0x开头
//输出6c38
char han1 = 0x6c38;
System.out.println(han1);
//输出永
|
也就是说,只要我们正确地读入了汉字“永”字,那么它在内存中的表示形式一定是0x6c38,没有其他任何值能替代这个字。
JVM的折中约定使得一个字符分为两部分:JVM内部和OS的文件系统。在JVM内部,统一使用Unicode表示,当这个字符被从JVM内部移到外部(即保存为文件系统中的一个文件的内容时),就进行了编码转换,使用了具体的编码方案。因此可以说所有的编码转换只发生在边界的地方,JVM和OS的交界处,也就是各种输入/输出流(或者Reader,Writer类)起作用的地方。
所有的I/O基本上可以分为两大阵营:面向字符的输入/输出流;面向字节的输入/输出流。这个“面向”是指这些类在处理输入/输出的时候,在哪个意义上保持一致。
如果面向字节,那么这类工作要保证系统中的文件二进制内容和读入JVM内部的二进制内容一致,不能变换任何0和1的顺序。这种输入/输出方式很适合诸如视频文件或者音频文件,因为不需要变换任何文件内容。
而面向字符的I/O是指希望系统中的文件的字符和读入内存的“字符”要一致。例如:我们的中文版XP系统上有一个GBK的文本文件,其中有一个“永”字,我们不关心这个字的GBK编码是什么,只希望在使用面向字符的I/O把它读入内存并保存在一个char型变量中时,I/O系统不要直接把“永”字的GBK编码放到这个字符(char)型变量中,我们不关心这个char型变量具体的二进制内容到底是多少,只希望这个字符读进来之后仍然是“永”字。
从这个意义上可以看出,面向字符的I/O类,也就是Reader和Writer类,实际上隐式做了编码转换,在输出时,将内存中的Unicode字符使用系统默认编码方式进行了编码,而在输入时,将文件系统中已经编码过的字符使用默认编码方案进行了还原。这里要注意,Reader和Writer只会使用这个默认的编码来做转换,而不能为一个Reader和Writer指定转换时使用的编码。这也意味着,如果使用中文版WindowsXP系统,其中存放了一个UTF8编码的文件,当采用Reader类来读入的时候,它还会用GBK来转换,转换后的内容当然不对。这其实是一种傻瓜式的功能提供方式,对大多数初级用户(以及不需要跨平台的高级用户,windows一般采用GBK,linux一般采用UTF8)来说反而是一件好事。
如果用到GBK编码以外的文件,就必须采用编码转换:一个字符与字节之间的转换。因此,Java的I/O系统中能够指定转换编码的地方,也就是在字符与字节转换的地方,那就是InputStremReader与OutputStreamWriter。这两个类是字节流和字符流的适配器类,它们承担编码转换的任务。
既然java是用unicode来编码字符,”我”这个中文字符的unicode就是2个字节。String.getBytes(encoding)方法是获取指定编码的byte数组表示,通常gbk/gb2312是2个字节,utf-8是3个字节。如果不指定encoding则取系统默认的encoding。
例如
1
2
3
4
5
6
7
8
9
10
11
|
//UTF8汉字占三个字节
b = str.getBytes("UTF-8");
System.out.println("UTF8编码格式下,一个汉字占" + b.length + "字节");
//混乱,很诡异,不理解!!!!!!
b = str.getBytes("UTF-16");
System.out.println("UTF16编码格式下,一个汉字占" + b.length + "字节");
//ANSI码小于128的字符占一个字节,其余占俩字节
b = str.getBytes();
System.out.println("默认编码" + System.getProperty("file.encoding") + "编码格式下,一个汉字占" + b.length + "字节");
|
由于JDK是国际版的,在编译的时候,如果我们没有用-encoding参数指定我们的JAVA源程序的编码格式,则javac.exe首先获得我们操作系统默认采用的编码格式,也即在编译java程序时,若我们不指定源程序文件的编码格式,JDK首先获得操作系统的file.encoding参数(它保存的就是操作系统默认的编码格式,如WIN2k,它的值为GBK),然后JDK就把我们的java源程序从file.encoding编码格式转化为JAVA内部默认的UNICODE格式放入内存中。然后,javac把转换后的unicode格式的文件进行编译成.class类文件,此时.class文件是UNICODE编码的,它暂放在内存中,紧接着,JDK将此以UNICODE编码的编译后的class文件保存到我们的操作系统中形成我们见到的.class文件。对我们来说,我们最终获得的.class文件是内容以UNICODE编码格式保存的类文件,它内部包含我们源程序中的中文字符串,只不过此时它己经由file.encoding格式转化为UNICODE格式了。
Java与编码问题串讲之二–如何理解java采用Unicode编码的更多相关文章
- 如何理解java采用Unicode编码
http://blog.csdn.net/gjb724332682/article/details/43229563 Java中字符仅以一种形式存在,那就是Unicode.由于java采用unicod ...
- java提高篇(二)-----理解java的三大特性之继承
在<Think in java>中有这样一句话:复用代码是Java众多引人注目的功能之一.但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情.在这句 ...
- 从 CPU 讲起,深入理解 Java 内存模型!
Java 内存模型,许多人会错误地理解成 JVM 的内存模型.但实际上,这两者是完全不同的东西.Java 内存模型定义了 Java 语言如何与内存进行交互,具体地说是 Java 语言运行时的变量,如何 ...
- app开发历程————服务器端生成JSON格式数据,采用Unicode编码,隐藏中文
今天,问以前的同事,他们写接口按什么编码,怎么看到有\u的一些看不懂的内容,一问,原来是信息隐藏,防止信息泄漏. 然后在网上查了Java如何把中文转换成unicode编码,转自:http://blog ...
- Java集合详解(一):全面理解Java集合
概述 Java所有集合类都在java.util包下,支持并发的集合在java.util.concurrent(juc)包下. 集合与数组区别: 数组大小是固定的,集合大小可以根据使用情况进行动态扩容. ...
- Java虚拟机运行时栈帧结构--《深入理解Java虚拟机》学习笔记及个人理解(二)
Java虚拟机运行时栈帧结构(周志明书上P237页) 栈帧是什么? 栈帧是一种数据结构,用于虚拟机进行方法的调用和执行. 栈帧是虚拟机栈的栈元素,也就是入栈和出栈的一个单元. 2018.1.2更新(在 ...
- VS2010与VS2013中的多字节编码与Unicode编码问题
1. 多字节字符与单字节字符 char与wchar_t 我们知道C++基本数据类型中表示字符的有两种:char.wchar_t. char叫多字节字符,一个char占一个字节,之所以叫多字节字符是因 ...
- 【由浅入深理解java集合】(二)——集合 Set
上一篇文章介绍了Set集合的通用知识.Set集合中包含了三个比较重要的实现类:HashSet.TreeSet和EnumSet.本篇文章将重点介绍这三个类. 一.HashSet类 HashSet简介 H ...
- 别翻了,这篇文章绝对让你深刻理解java类的加载以及ClassLoader源码分析【JVM篇二】
目录 1.什么是类的加载(类初始化) 2.类的生命周期 3.接口的加载过程 4.解开开篇的面试题 5.理解首次主动使用 6.类加载器 7.关于命名空间 8.JVM类加载机制 9.双亲委派模型 10.C ...
随机推荐
- 使用flume将kafka数据sink到HBase【转】
1. hbase sink介绍 1.1 HbaseSink 1.2 AsyncHbaseSink 2. 配置flume 3. 运行测试flume 4. 使用RegexHbaseEventSeriali ...
- 【Windows】windows核心编程整理(下)
windows核心编程整理(上) windows核心编程整理(下) 线程的堆栈 每当创建一个线程时,系统就会为线程的堆栈(每个线程有他自己的堆栈)保留一个堆栈空间区域,并将一些物理存储器提交给这个以保 ...
- [Java]随记--HttpClient发送put请求
http://blog.csdn.net/u010989191/article/details/52852155 ******************************************* ...
- iOS开发:代码通用性以及其规范 第一篇(附带,自定义UITextView\进度条\双表显示\瀑布流 代码设计思路)
在iOS团队开发中,我见过一些人的代码,也修改过他们的代码.有的人的代码写的非常之规范.通用,几乎不用交流,就可以知道如何修改以及在它基础上扩展延生.有的人的代码写的很垃圾,一眼看过去,简直会怀疑自己 ...
- wamp安装xdebug特殊情况win7 64位安装32位wamp
在wamp上安装xdebug网上很多文章都介绍了方法,但是我这里遇到了一个很特殊的情况,在网上很少有人提及: 我机器是win7 64位的,安装的wamp1.7.4是32位的,这是后来导致出现奇怪现象的 ...
- Bootstrap tab插件的使用
菜鸟教程链接:http://www.runoob.com/bootstrap/bootstrap-tab-plugin.html 1.例子 <!DOCTYPE html> <html ...
- 解决Eclipse异常关闭后重启报 org.eclipse.swt.SWTException: Invalid thread access 的问题
. . . . . 很久没有写博客了,最近实在是太忙,一直想写点干货,但是一直没静下心来学习. 今天又在加班忙碌之中,结果谁知道越忙碌越出问题.先是 weblogic 没有正常启动,凭经验第一反应就是 ...
- react学习资源
http://www.ruanyifeng.com/blog/2015/03/react.html http://www.ruanyifeng.com/blog/2015/02/future-of-d ...
- rsa.FromXmlString 系统找不到指定的文件
rsa做加密解密的时候,发布到IIS7 Windows2008上出现异常,提示rsa.FromXmlString找不到指定的文件. 原因是系统安全性问题,做了变更,修改为如下代码即可: System. ...
- hbase 学习(十四)Facebook针对hbase的优化方案分析
使用hbase的目的是为了海量数据的随机读写,但是在实际使用中却发现针对随机读的优化和gc是一个很大的问题,而且hbase的数据是存储在Hdfs,而Hdfs是面向流失数据访问进行设计的,就难免带来效率 ...