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. Python数据分析 EPD

    参考用书 <利用Python进行技术分析:Python for Data Analysis> 官方把epd (https://www.enthought.com/products/cano ...

  2. 电商模式O2O、C2C、B2B、B2C

    电商模式O2O.C2C.B2B.B2C o2o o2o 是 online to offline 分为四种运营模式 1.online to offline 是线上交易到线下消费体验 2.offline ...

  3. 0k6410定时器详细分析

    看到一篇很好的博文,分析2410定时器中断的使用的,很详细,和大家分享一下 转载来源于http://www.cnblogs.com/Neddy/archive/2011/07/01/2095176.h ...

  4. C#中查询字符串中是否包含指定字符/串,使用IndexOf还是Contains?

    C#中查询字符串中是否包含指定字符/串,使用IndexOf还是Contains?这是一个很常见的命题,以前也没有注意,今天QQ群里有人提起,于是就做了下试验,代码如下: using System; u ...

  5. saltstack系列(五)——zmq扩展(一)

    问题 假设我们的一个客户端既有pull又有sub,他们两个都需要接收消息,该如何协调呢,毕竟,当一个socket要收消息的时候,函数recv是阻塞的,所以,我们第一个思路是不让它阻塞? 实例代码: # ...

  6. init方法返回值自动改写问题

    [init方法返回值自动改写问题] 在ARC开启的情况下,以init开头的实例方法的返回值会被默认无视,返回类型会被编译器改写为类指针类型. 如一人类叫UIButton类,如果一个方法叫 (UILab ...

  7. 面试题:java实例变量,局部变量,类变量 背1

    一.实例变量 也叫对象变量.类成员变量:从属于类由类生成对象时,才分配存储空间,各对象间的实例变量互不干扰,能通过对象的引用来访问实例变量.但在Java多线程中,实例变量是多个线程共享资源,要注意同步 ...

  8. Django开发——集成的子框架django.contrib

    Django开发——集成的子框架django.contrib 2018年09月11日 19:32:42 Mrkang1314 阅读数:63  https://blog.csdn.net/mashaok ...

  9. Eclipse中新建applet 错误

    出现的问题:  “错误,请单击以获取详细信息” Java Plug-in 1.6.0_45 使用 JRE 版本 1.6.0_45-b06 Java HotSpot(TM) Client VM 用户主目 ...

  10. C#获取文件的Content-Type(MIME Type)的方法

    使用静态类MimeMapping(需要.NET Framework 4.5及以后的支持) string fileName = "D:\myfile.txt"; var conten ...