论坛首页 Java企业应用论坛

对编码问题的总结(java版)

浏览 19143 次
精华帖 (0) :: 良好帖 (7) :: 新手帖 (1) :: 隐藏帖 (0)
作者 正文
   发表时间:2010-11-06   最后修改:2010-11-10

      总结下这两天对编码的认识一些认识,本文显得比较啰嗦,应为这是我探讨的整个流程结果,了解的有不对的地方多多指点出来!

      不了解的相信你会有个不错的认解,这是我学习编程的一个开始,大家就多多帮村。

      在查看网上一些资料时候,首先第一个奇怪的现象出了,据说是移动打不过联通的根本原因。
      如果你的电脑操作系统是win2000或winxp的话,那么:
      1、在桌面上点右键,选择新建 - 文本文档;
      2、打开“新建 文本文档“,录入“移动“两字后存盘退出;
      3、重新打开“新建 文本文档“,看到什么了?
      4、是不是刚刚录入的“移动“两字?
      咱们换过来
      1、在桌面上点右键,选择新建 - 文本文档;
      2、打开“新建 文本文档“,录入“联通“两字后存盘退出;
      3、重新打开“新建 文本文档“,看到什么了?
      4、是不是刚刚录入的“联通“两字不见了,取而代之是个烧焦的手机电池的摸样?
      呵呵,是不是很有趣,自己试一下,如果重新建个,除了键入“联通”还多敲几个字,“联通”又能正常显示啦。
      (以下说的是中文的系统)这个道理还是挺明显的,简单的说文本他本身默认存入编码为GBK,但是“联通”二字的二进制格式跟utf-8编码的格式相同,所以再次打开的时候就是系统用了utf-8的格式去解读了gbk的文本,所以出现乱码。


      首先了解下上网了解下so8859-1,GB2312/GBK,unicode,utf-8,utf-16等编码的背景资料以及各自关系。
      接下来自己又对了java编程做了些实验,我以“连通”二字做了实验,应为不想对不住联通,“连通”二字解成GBK二进制码后也是符合utf-8编码的二进制码格式。 这个问题晚上查一下一大堆,在这里就不多说了。
      接下来是探讨java运行时的编码转换,好,开始建立一个文本,输入“连通”二字,默认保存。


      测试程序

 

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

public class Charset {
	public static void main(String[] str) {
		System.out.println(System.getProperty("file.encoding"));
		FileInputStream fis01;
		FileInputStream fis02;
		FileInputStream fis03;
		InputStreamReader isrUTF8;
		InputStreamReader isrGBK;
		BufferedReader brUTF8;
		BufferedReader brGBK;
		try {
			fis01 = new FileInputStream("E:\\试一下.txt");
			fis02 = new FileInputStream("E:\\试一下.txt");
			fis03 = new FileInputStream("E:\\试一下.txt");
			isrGBK = new InputStreamReader(fis02, "GBK");
			isrUTF8 = new InputStreamReader(fis01, "UTF-8");
			brGBK = new BufferedReader(isrGBK);
			brUTF8 = new BufferedReader(isrUTF8);
			int t = 0;
			String strGBK = brGBK.readLine();
			String strUTF8 = brUTF8.readLine();
			System.out.println("GBK的字节-----");
			byte[] b = strGBK.getBytes();
			for (int i = 0; i < b.length; i++) {
				System.out.println(b[i]);
			}
			System.out.println("-----");
			System.out.println("utf-8的字节-----");
			byte[] c = strUTF8.getBytes();
			for (int i = 0; i < c.length; i++) {
				System.out.println(c[i]);
			}
			System.out.println("-----");
			System.out.println("直接读取的字节-----");
			byte[] y = new byte[b.length];
			int f = fis03.read(y);
			for (int d = 0; d < y.length; d++) {
				System.out.println(y[d]);
			}
			System.out.println("-----");
			System.out.println("GBK:" + strGBK);
			System.out.println("UTF-8:" + strUTF8);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 

 

 

很简单的一个程序,结果为

GBK

GBK的字节----- -63 -84 -51 -88
-----
utf-8的字节----- 63 63 63
-----
直接读取的字节----- -63 -84 -51 -88
-----
GBK:连通
UTF-8:???


如图运行过程如图: 





     源代码为本机默认编码(即GBK),在读取二进制后通过,因为在Java 语言默认的编码方式是UNICODE,单我们读取一个文本时,首先读取二进制,通过isrGBK = new InputStreamReader(fis02, &quot;GBK&quot;)用GBK编码将二进制码解析成UNICODE编码存在JVM虚拟内存里;当要打印输出,或是获取二进制码时,用byte[] b = strGBK.getBytes()(默认就是byte[] b = strGBK.getBytes(“gbk”)),UNICODE作为内存的与其他外来流的中间者沟通个个编码转换。

      如果不指定,就是默认编码就是GBK,一般情况下就是我们存的是“GBK”,读出来的也是“GBK”,所以一般情况下不会出现乱码问题,接下来把上面的文本在保存时指定存为UTF-8时,得到结果为

GBK
GBK的字节-----
-17 -69 -65 -24 -65 -98 -23 -128 63
-----
utf-8的字节----- 63 -63 -84 -51 -88
-----
直接读取的字节----- -17 -69 -65 -24 -65 -98 -23 -128 -102
-----

GBK:锘胯繛閫?
UTF-8:?连通



运行过程: 




     可以看到,二进制 -17-69-65  这三个是编码标识符,说明这是一个UTF-8编码的文本,用UTF-8解析-24-65-98等于“连”,-23-128-102=“通。


总结就引用一下网上看到的一句话:

       事实上,世界上任何东西要与其他东西通信会话,都存在一个既定的协议,既定的编码。人与人之间通过文字联络,汉字“妈”代表生你的那个人,这就是一种既定的编码。但注意到这样一种情况,汉字“妈”在日本文字里有可能是你生下的那个人,所以当一个中国人A与日本B之间用“妈”这个字进行交流,出现误解就很正常的。用记事本打开二进制文件与上面的情况类似。记事本无论打开什么文件都按既定的字符编码工作(如ASCII码),所以当他打开二进制文件时,出现乱码也是很必然的一件事情了,解码和译码不对应嘛。

杂谈:

      由于自己写的还有些地方说得比较模糊,看了别人的文章,写得太好了 http://www.iteye.com/topic/311583内部很清晰,语言精炼标准。

      自己代码试出,原来utf-16就是unicode编码,应该是unicode字集开始时候只有unicode编码,但后来出现了utf-8编码,为了名字统一好看,给unicode编码多加了个名字叫utf-16编码。。

       接下网上查到:UTF-16直接就是unicode编码, 没有变换, 但它包含了0x00在编码内, 头256字节码的第一个byte都是0x00, 在操作系统(C语言)中有特殊意义, 会引起问题。 

     红色的这两段字,都为自己理解,第一句更是自己的猜想理解,(事实肯定不是这样,让自己好记点,呵呵)想具体认识,查看些官方类文旦。
     
     自己之前也混淆字符集跟编码两个概念,特地链接过来http://www.iteye.com/topic/317895。 
      这里贴了一些较权威的资料,贴上帮助学习http://drift-ice.iteye.com/blog/726265

现在就纠正下上面红色的概念问题:

     Unicode是为整合全世界的所有语言文字而诞生的。任何文字在Unicode中都对应一个值,这个值称为代码点(code point)。代码点的值通常写成 U+ABCD 的格式。而文字和代码点之间的对应关系就是UCS-2(Universal Character Set coded in 2 octets)。顾名思义,UCS-2是用两个字节来表示代码点,其取值范围为 U+0000~U+FFFF。

为了能表示更多的文字,人们又提出了UCS-4,即用四个字节表示代码点。它的范围为 U+00000000~U+7FFFFFFF,其中 U+00000000~U+0000FFFF和UCS-2是一样的。

要注意,UCS-2和UCS-4只规定了代码点和文字之间的对应关系,并没有规定代码点在计算机中如何存储。规定存储方式的称为UTF(Unicode Transformation Format),其中应用较多的就是UTF-16和UTF-8了。

 

 

 

 

 

    主要上文主要说的unicode编码主要是说:java中的string.getByte("unicode")出来的是utf-16,呵呵。

这段话可以帮助理解:Windows平台下默认的Unicode编码为Little Endian的UTF-16.



     

 

  • 大小: 6.3 KB
   发表时间:2010-11-06   最后修改:2010-11-06
支持&收藏,与LZ来自同一个城市。
0 请登录后投票
   发表时间:2010-11-07  
支持.  与LZ来之同一星球
0 请登录后投票
   发表时间:2010-11-07  
IcyFenix 写道
支持&收藏,与LZ来自同一个城市。

呀,不知道在哪个区工作啦~
0 请登录后投票
   发表时间:2010-11-07  
marauder 写道

如图运行过程如图: 





   

中间的那个byte[] 不=63 63 好像少了个63  ,最右边的byte[]b = 63 -84 -51 -88也少了个在下面一行呀。

支持,收藏。

0 请登录后投票
   发表时间:2010-11-07  
楼主动手深入分析的精神小弟佩服.先留着,后续慢慢看.
0 请登录后投票
   发表时间:2010-11-07  
codermouse 写道
楼主动手深入分析的精神小弟佩服.先留着,后续慢慢看.

写得很啰嗦,就是因为网上找了些的资料,但不确定内存那部分存的是什么,所以把整个运行过程给虚拟出来。
希望多多交流,有错误,或是描述不够正确请指正。
0 请登录后投票
   发表时间:2010-11-07  
wuyanlong 写
  

中间的那个byte[] 不=63 63 好像少了个63  ,最右边的byte[]b = 63 -84 -51 -88也少了个在下面一行呀。

支持,收藏。


确实是,看得很仔细,但是这是个小问题,他本来就是乱码,是图片没弄完整后面63显示不出来,byte[]=63 -84 -51 -88那没错,下面是换行符

编程很多时候需要细心,谢谢,以后会注意

希望多多交流,有错误,或是描述不够正确请指正。

0 请登录后投票
   发表时间:2010-11-07  
unicode是一种字符集.与GB2312,GBK是同概念的.就是一种代码表.

而utf-8,utf-16这些不是字符集,而是用来表达unicode字符的数据格式.utf-8最大的特点是变长,这样对于英文语言国家来说,从iso8859-1转为utf-8后,字符串的尺寸增加也不是很大.

另外,说到编码,一方面要注意字符编码,同样还要注意文件编码概念.也就是可能出现文件编码声明为ASNI,而存储的字符内容为GBK之类的情况.
然后,对于UTF-8格式的文件,最烦心的是BOM头问题...

总之,我的心得体会是,不管总结多少次,编码问题总还是会成为问题... ...
0 请登录后投票
   发表时间:2010-11-07  
会思考才能立于不败之地,果断收藏
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics