http://blog.csdn.net/gjb724332682/article/details/43229563

Java中字符仅以一种形式存在,那就是Unicode。由于java采用unicode编码,char 在java中占2个字节。2个字节(16位)来表示一个字符。
这里的Java中是指在JVM中、在内存中、在代码里声明的每一个char、String类型的变量中。
例如:

  1. public static void main(String[] args) {
  2. System.out.println(System.getProperty("file.encoding"));//输出UTF-8
  3. char han = '永';
  4. System.out.format("%x", (short) han);//输出6c38
  5. char han1 = 0x6c38;
  6. System.out.println(han1);//输出永
  7. }

也就是说,只要我们正确地读入了汉字“永”字,那么它在内存中的表示形式一定是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. public static void main(String[] args) throws UnsupportedEncodingException {
  2. byte[] b;
  3. String str = "测";
  4. //UTF8编码格式下,一个汉字占3字节
  5. b = str.getBytes("UTF-8");
  6. System.out.println("UTF8编码格式下,一个汉字占" + b.length + "字节");
  7. //UTF16编码格式下,一个汉字占4字节
  8. b = str.getBytes("UTF-16");
  9. System.out.println("UTF16编码格式下,一个汉字占" + b.length + "字节");
  10. //默认编码UTF-8编码格式下,一个汉字占3字节
  11. b = str.getBytes();
  12. System.out.println("默认编码" + System.getProperty("file.encoding") + "编码格式下,一个汉字占" + b.length + "字节");
  13. }

注意,file.encoding在ide和直接用命令行输出可能不一致,ide比如eclipse,idea等可以配置这个编码。如下图的Project Encoding。

由于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格式了。如果IDE设置了file.encoding为UTF-8,那么保存这些代码的文件编码就是UTF-8,如果这时候,在编码为GBK的系统上用javac命令编译这个类,并执行,那么结果会输出乱码。如果在IDE里编译执行,就不会输出乱码。

如何理解java采用Unicode编码的更多相关文章

  1. Java与编码问题串讲之二–如何理解java采用Unicode编码

    Java开发者必须牢记:在Java中字符仅以一种形式存在,那就是Unicode(不选择任何特定的编码,直接使用他们在字符集中的编号,这是统一的唯一方法).由于java采用unicode编码,char  ...

  2. java测试Unicode编码以及数组的运用(初学篇)

    /*第二章第四小题*/ /* * (1)编写一个应用程序,给出汉字“你” ,“我”,“他”在Unicode 表中的位置 * (2)编写一个java应用程序,输出全部的希腊字母 */ public cl ...

  3. 在 Java 中将 Unicode 编码的汉字转码

    今天在做一个新浪微博的抓取测试,发现抓取后的内容是Unicode编码的,完全找不到熟悉的汉字了,下面搜索出来的一种方法,完全可行,只是不知到Java内部是否提供了相关的类库. 实现方法如下: publ ...

  4. app开发历程————服务器端生成JSON格式数据,采用Unicode编码,隐藏中文

    今天,问以前的同事,他们写接口按什么编码,怎么看到有\u的一些看不懂的内容,一问,原来是信息隐藏,防止信息泄漏. 然后在网上查了Java如何把中文转换成unicode编码,转自:http://blog ...

  5. JAVA转化Unicode编码

    package yyl.example.basic.codec; import java.util.Locale; import java.util.regex.Matcher; import jav ...

  6. 如何理解Java程序使用Unicode字符集编写

    Java采用UTF-16编码作为内码,也就是说在JVM内部,文本是用16位码元序列表示的,常用的文本就是字符(char)和字符串(String)字面常量的内容.注:UTF-16是Unicode字符集的 ...

  7. java基础类型中的char和byte的辨析及Unicode编码和UTF-8的区别

    在平常工作中使用到char和byte的场景不多,但是如果项目中使用到IO流操作时,则必定会涉及到这两个类型,下面让我们一起来回顾一下这两个类型吧. char和byte的对比 byte byte 字节, ...

  8. unicode 编码总结

    unicode简介: unicode又称为unicode character set,缩写为ucs,意为字符集.编码方式有utf-7,utf-8,utf-16,utf-32几种,常用的是utf-8和u ...

  9. ASCII\UNICODE编码的区别

    前几天,Google给我Hotmail邮箱发了封确认信.我看不懂,不是因为我英文不行,而是"???? ????? ??? ????"的内容让我不知所措.有好多程序员处理不好编码问题 ...

随机推荐

  1. GET、POST详解 --转自http://hi.baidu.com/richarwu/item/bd43633a6ba62986b611dbcd

    HTTP Get,Post请求详解 请求类型 三种最常见的请求类型是:GET,POST 和 HEAD GET:获取一个文档 大部分被传输到浏览器的html,images,js,css, … 都是通过G ...

  2. Flask之数据库操作

    4.2 数据库基本操作 在Flask-SQLAlchemy中,插入.修改.删除操作,均由数据库会话管理.会话用db.session表示.在准备把数据写入数据库前,要先将数据添加到会话中然后调用comm ...

  3. leetcode216

    public class Solution { public IList<IList<int>> CombinationSum3(int k, int n) { , , , , ...

  4. struts2中s:iterator的使用(2个list嵌套循环)

    <s:iterator value="packagePlateTbls" id="plateTbls"> <tr> <td cla ...

  5. mysql之约束以及修改数据表

    数据约束的分类: ———————————————————————————————————————————————————— 外键约束的要求解析: //在my文件中的这句话代表着搜索引擎,如果不是的就需 ...

  6. 调用DLL的2种方式

    [调用DLL的2种方式] DLL在生成的时候会有dll.lib2个文件,另外包含相应的.h. 1.静态方式,通过lib来引用dll,以及引入.h. 2.只通过dll来使用,前提是知道内部的函数符号.

  7. ZOJ 3956 Course Selection System

    题意 有n节课可供选择,每节课都有两个值Hi和Ci,如果学生选择了m节课(x1,x2,....,xm),则它的舒适值被定义为: //这里没有公式((lll¬ω¬)),因为那个图片我保存不下来≧ ﹏ ≦ ...

  8. Qt5信号和槽机制

    信号槽是 Qt 框架引以为豪的机制之一.熟练使用和理解信号槽,能够设计出解耦的非常漂亮的程序,有利于增强我们的技术设计能力. 所谓信号槽,实际就是观察者模式.当某个事件发生之后,比如,按钮检测到自己被 ...

  9. Linux ekho

    一.简介 Ekho(余音)是一个免费.开源的中文语音合成软件.它目前支持粤语.普通话(国语).诏安客语.藏语.雅言(中国古代通用语)和韩语(试验中),英文则通过Festival间接实现.Ekho支持L ...

  10. R语言的并行运算(CPU多核)

    通常R语言运行都是在CPU单个核上的单线程程序.有时我们会有需求对一个向量里的元素应用相同的函数,最终再将结果合并,并行计算可以大幅节约时间. 为了支持R的并行运算, parallel包已经被纳入了R ...