JAVA里字符编码的探索与理解

编码

 今天终于把JAVA里一个比较头痛的问题——字符编码弄清晰了,所以写一篇文章来纪念一下,也为大家提供一点自己的心得。

众所周知,JAVA为了国际通用,用的是UNICODE来保存里面的字符。而UNICODE只是一个种字符集,字符的存储和表示要用到一定的字符编码格式,而与UNICODE对应的字符编码格式就是我们常看到的UTF-8,UTF-16等等,而UTF-8是最常用的,所以人们常常把它和UNICODE等同起来(我以前就是这样的),这在某些情况下是没有错的,但这样的理解在JAVA里就会产生一些混淆。我们用下面的程序来演示一下。

定义一个字符串

String name = "堂";

这个字符串就一个字符,把它取出来

char c_name = name.charAt(0);

JAVA里的char型是十六位的(两个字节),但是如果是用UTF-8的话可能会不只两位(UTF-8是变长存储的),那看来JAVA本身并不是用UTF-8来保存的,口说无凭,做个实验吧。
首先看看char里保存的内容

int low = (c_name) & 0xff;//取c_name的低位

int high = (c_name >> 8) & 0xff;//取c_name的高位

System.out.println(Integer.toHexString(high) + " " + Integer.toHexString(low));

结果是58 02

只有两个字节而已(16位),那么真正的UTF-8编码的内容是什么呢,再看看吧。

为了方便,我写了一个辅助方法printbyte,作用是把一个byte数组的每个元素按照十六进制格式打印出来,同样为了方便,我把它作为静态方法。

public static void printbyte(byte[] bt)

{

for (int i = 0; i < bt.length; i++)

{

int hex = (int)bt[i] & 0xff;

System.out.print(Integer.toHexString(hex) + " ");

}

System.out.println(" length = "+bt.length);

}

byte[] utf_8 = name.getBytes("utf-8");

printbyte(utf_8);

结果是e5 a0 82 length = 3

哇,三个字节!看来JAVA内部用的真不是UTF-8,那用的是什么呢?UTF-16?看一下便知。

byte[] utf_16 = name.getBytes("utf-16");

printbyte(utf_16);

结果是fe ff 58 02 length = 4,靠,四个字节了。咦?后面的低16位不正是和开始c_name的十六进制表示一样的吗?看来JAVA真正的内部字符编码和UTF-16有或多或少的联系。JAVA内部究竟是用的什么字符编码呢?这个问题我也找了很久,后来在THINK IN JAVA 3rd的12章里看到一个例子出现了UTF-16BE,难道是它?

byte[] utf_16be = name.getBytes("utf-16be");

printbyte(utf_16be);

结果出来了:58 02 length = 2

哈哈,I got it!不多不少两个字节,内容也一样。果然是它。同时我在里面也看到,UNICODE的编码还有一个LE,这里的BE,LE我想应该是bigendian和littleendian吧。

好了,JAVA里字符的编码总算搞清楚了,这是本人的第一篇原创文章,可能很肤浅。如果有什么不对的地方请大家慷慨指教!谢谢。

时间: 2024-09-17 03:41:36

JAVA里字符编码的探索与理解的相关文章

字符编码详解——彻底理解掌握编码知识,“乱码”不复存在

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://polaris.blog.51cto.com/1146394/377468  每一个程序员都不可避免的遇到字符编码的问题,特别是做Web开发的程序员,"乱码问题"一直是让人头疼的问题,也许您已经很少遇到"乱码"问题,然而,对解决乱码的方法的内在原理,您是否明白?本人作为一个程序员,在字符编码方面同样遇到不少问题,而且一直对各种编码懵懵懂懂.不清不楚:

关于java中字符编码的一点心得,可能对初学者有点帮助

编码|初学|心得 这是张孝祥老师的java就业培训视频教程里面的一道题目有所变动编写下面的程序代码分析和观察程序的运行结果 import java.io.*;public class TestCodeIO {      public static void main(String[] args) throws Exception{            InputStreamReader isr = new InputStreamReader(System.in,"iso8859-1"

求解关于JAVA中字符编码的问题

问题描述 我们都知道JAVA中的char类型是占两个字节,如下:publicclassgetcharcode{publicstaticvoidmain(String[]args){Strings="A";Stringr="王";System.out.println(s.getBytes().length);System.out.println(r.getBytes().length);Charactera='a';Characterb='啊';Integerc=5;

问个字符编码的问题java

问题描述 问个字符编码的问题java unicode字符编码,gbk是英文一个字节中文2个字节,utf-8是英文一个字节,中文3个字节.可在java中,char型数据无论中英文都是2个字节,char型数据是对应什么什么编码?还有什么字符编码可否简单的介绍一二? 解决方案 编码多呢.这是我电脑上安装的所有编码 IBM EBCDIC (US-Canada)OEM United StatesIBM EBCDIC (International)Arabic (ASMO 708)Arabic (DOS)G

我的Java开发学习之旅------&amp;gt;Java字符编码解析

Java开发中,常常会遇到乱码的问题,一旦遇到这种问题,常常就很扯蛋,每个人都不愿意承认是自己的代码有问题.其实编码问题并没有那么神秘,那么不可捉摸,搞清Java的编码本质过程就真相大白了.               其实,编码问题存在两个方面:JVM之内和JVM之外.   1.Java文件编译后形成class 这里Java文件的编码可能有多种多样,但Java编译器会自动将这些编码按照Java文件的编码格式正确读取后产生class文件,这里的class文件编码是Unicode编码(具体说是UT

Java中的字符编码问题处理心得总结_java

当面对一串字节流的时候,如果不指定它的编码,其实际意义是无法知道的. 这句话应该也是我们面对"字符转字节,字节转字符"问题时候时刻记在脑子里的.否则乱码问题可能就接踵而至. 其实乱码问题的本质就是Encoding和Decoding用的不是一个编码,明白了这个道理就很好解决乱码问题了. Java中常见的时候有如下: 1. String类使用byte[]的构造函数 String(byte[] bytes),String类同时提供了两个重载 (1)String(byte[] bytes, C

JAVA之旅(三十)——打印流PrintWriter,合并流,切割文件并且合并,对象的序列化Serializable,管道流,RandomAccessFile,IO其他类,字符编码

JAVA之旅(三十)--打印流PrintWriter,合并流,切割文件并且合并,对象的序列化Serializable,管道流,RandomAccessFile,IO其他类,字符编码 三十篇了,又是一个阳光明媚的周末,一个又一个的周末,周而复始,不断学习,前方的路你可曾看见?随我一起走进技术的世界,流连忘返吧! 一.打印流PrintWriter 打印流有PrintWriter和PrintStream,他的特点可以直接操作输入流还有文件 该流提供了打印方法,可以将各种数据类型原样打印 file对象

Java 字符编码问题

编码|问题 1.关于文件编码 一般文件保存(文本文件),在保存的时候按系统默认语言编码(字符集)保存, 在中文系统上是GBK,英文系统上是ISO8859_1, 日文系统上是MS932. 在打开的时候同样是按当前系统默认语言(字符集)编码去解码,所以一些中文汉字在日文系统上会显示乱码的原因就是这个. 说白了也就是打开文件时候不同平台使用的字符集不同, 例如中文字符集包括 a,b,c, 日文字符集包括a,b,当在日文系统上解码汉字c的时候,就会出现所谓的乱码. 2. java工作处理编码模式(1)j

java里的多态理解的模模糊糊的,到底什么是多态?多态和类是什么关系?和对象呢?

问题描述 java里的多态理解的模模糊糊的,到底什么是多态?多态和类是什么关系?和对象呢? java里的多态理解的模模糊糊的,到底什么是多态?多态和类是什么关系?和对象呢? 解决方案 多态,顾名思义就是一种概念,多种形态. 在Java中,泛型.继承和复写方法.函数重载都体现了多态. 具体你可以看维基百科上对应的词条. 解决方案二: 你只要记住 1.同一类中,方法的**重载**是多态的体现. 2.在不同的类中(继承),方法的**重写**也是多态的体现 解决方案三: 需要搞清楚面向对象的三大特征,封