﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-IT Life-文章分类-J2se-&gt;encoding</title><link>http://www.blogjava.net/tony/category/13565.html</link><description /><language>zh-cn</language><lastBuildDate>Sun, 11 Mar 2007 03:08:35 GMT</lastBuildDate><pubDate>Sun, 11 Mar 2007 03:08:35 GMT</pubDate><ttl>60</ttl><item><title>java中中文问题详解（转自www.javajia.com）</title><link>http://www.blogjava.net/tony/articles/60666.html</link><dc:creator>tony-dl</dc:creator><author>tony-dl</author><pubDate>Fri, 28 Jul 2006 14:55:00 GMT</pubDate><guid>http://www.blogjava.net/tony/articles/60666.html</guid><wfw:comment>http://www.blogjava.net/tony/comments/60666.html</wfw:comment><comments>http://www.blogjava.net/tony/articles/60666.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/tony/comments/commentRss/60666.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/tony/services/trackbacks/60666.html</trackback:ping><description><![CDATA[预备知识： <br />　1.字节和unicode <br />　　Java内核是unicode的，就连class文件也是，但是很多媒体，包括文件/流的保存方式 <br />　　是使用字节流的。 因此Java要对这些字节流经行转化。char是unicode的，而byte是字节. <br />　　Java中byte/char互转的函数在sun.io的包中间有。其中ByteToCharConverter类是中调度， <br />　　可以用来告诉你，你用的Convertor。其中两个很常用的静态函数是 <br />　　 public static ByteToCharConverter getDefault() ; <br />　　 public static ByteToCharConverter getConverter(String encoding); <br />　　如果你不指定converter，则系统会自动使用当前的Encoding,GB平台上用GBK,EN平台上用 <br />　　8859_1 <br />　　 <br />　　我们来就一个简单的例子： <br />　　　　　"你"的gb码是：0xC4E3 ,unicode是0x4F60 <br />　　　　　你用: <br />　　　　　--encoding="gb2312"; <br />　　　　　--byte b[]={(byte)"u00c4",(byte)"u00E3"}; <br />　　　　　--convertor=ByteToCharConverter.getConverter(encoding); <br />　　　　　--char [] c=converter.convertAll(b); <br />　　　　　--for(int i=0;i 　　　　　--{ <br />　　　　　-- System.out.println(Integer.toHexString(c[i])); <br />　　　　　--} <br />　　　　　--打印出来是0x4F60 <br />　　　　　--但是如果使用8859_1的编码，打印出来是 <br />　　　　　--0x00C4,0x00E3 <br />　　　　　----例１ <br />　　　　 反过来： <br />　　　　 --encoding="gb2312"; <br />　　　　 　　　char c[]={"u4F60"}; <br />　　　　　　　 convertor=ByteToCharConverter.getConverter(encoding); <br />　　　　　--byte [] b=converter.convertAll(c); <br />　　　　　--for(int i=0;i 　　　　　--{ <br />　　　　　-- System.out.println(Integer.toHexString(b[i])); <br />　　　　　--} <br />　　　　　　--打印出来是：0xC4,0xE3 <br />　　　　　　----例２ <br />　　　　　　--如果用8859_1就是0x3F，?号，表示无法转化　　　　　　-- <br />　　　　　 很多中文问题就是从这两个最简单的类派生出来的。而却有很多类　　 <br />　　不直接支持把Encoding输入，这给我们带来诸多不便。很多程序难得用encoding <br />　　了，直接用default的encoding，这就给我们移植带来了很多困难 <br />　　-- <br />　　2.UTF-8 <br />　　--UTF-8是和Unicode一一对应的，其实现很简单 <br />　　-- <br />　　 -- 7位的Unicode: 0 _ _ _ _ _ _ _ <br />　　--11位的Unicode: 1 1 0 _ _ _ _ _ 1 0 _ _ _ _ _ _ <br />　　--16位的Unicode: 1 1 1 0 _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ <br />　　--21位的Unicode: 1 1 1 1 0 _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ <br />　　--大多数情况是只使用到16位以下的Unicode: <br />　　--"你"的gb码是：0xC4E3 ,unicode是0x4F60 <br />　　--我们还是用上面的例子 <br />　　--　　--例１：0xC4E3的二进制： <br />　　--　　--　　　 1 1 0 0 0 1 0 0 1 1 1 0 0 0 1 1 <br />　　--　　--　　　 由于只有两位我们按照两位的编码来排，但是我们发现这行不通， <br />　　--　　--　　　 因为第７位不是0因此，返回"?" <br />　　--　　--　　　 <br />　　--　　--例２：0x4F60的二进制： <br />　　--　　--　　　 0 1 0 0 1 1 1 1 0 1 1 0 0 0 0 0 <br />　　--　　--　　　 我们用UTF-8补齐，变成： <br />　　--　　--　　　 11100100 10111101 10100000 <br />　　--　　--　　　 E4--BD-- A0 <br />　　--　　--　　　 于是返回0xE4,0xBD,0xA0 <br />　　--　　-- <br />　　3.String和byte[] <br />　　--String其实核心是char[],然而要把byte转化成String，必须经过编码。 <br />　　--String.length()其实就是char数组的长度，如果使用不同的编码，很可 <br />　　--能会错分，造成散字和乱码。 <br />　　--例： <br />　　----byte [] b={(byte)"u00c4",(byte)"u00e3"}; <br />　　----String str=new String(b,encoding);　　---- <br />　　----如果encoding=8859_1，会有两个字，但是encoding=gb2312只有一个字　　---- <br />　　--这个问题在处理分页是经常发生 <br />　　4.Reader,Writer/InputStream,OutputStream <br />　　--Reader和Writer核心是char，InputStream和OutputStream核心是byte。 <br />　　--但是Reader和Writer的主要目的是要把Char读/写InputStream/OutputStream <br />--一个reader的例子： <br />--文件test.txt只有一个"你"字，0xC4,0xE3-- <br />--String encoding=; <br />--InputStreamReader reader=new InputStreamReader( <br />----new FileInputStream("text.txt"),encoding); <br />--char []c=new char[10]; <br />--int length=reader.read(c); <br />--for(int i=0;i ----System.out.println(c[i]); <br />　　--如果encoding是gb2312，则只有一个字符，如果encoding=8859_1，则有两个字符 <br />　　-------- <br />-- <br />-- <br />　　 <br />　　 ---- <br />　2.我们要对Java的编译器有所了解： <br />　--javac -encoding <br />　 我们常常没有用到ENCODING这个参数。其实Encoding这个参数对于跨平台的操作是很重要的。 <br />　 如果没有指定Encoding，则按照系统的默认Encoding,gb平台上是gb2312，英文平台上是ISO8859_1。　 <br />　--Java的编译器实际上是调用sun.tools.javac.Main的类，对文件进行编译，这个类　-- <br />　有compile函数中间有一个encoding的变量,-encoding的参数其实直接传给encoding变量。 <br />　编译器就是根据这个变量来读取java文件的，然后把用UTF-8形式编译成class文件。 <br />　一个例子： <br />　--public void test() <br />　--{ <br />　----String str="你"; <br />　----FileWriter write=new FileWriter("test.txt"); <br />　----write.write(str); <br />　----write.close(); <br />　--} <br />　----例３ <br />--如果用gb2312编译，你会找到E4 BD A0的字段 <br />-- <br />--如果用8859_1编译， <br />--00C4 00E3的二进制： <br />--00000000 11000100 00000000 11100011-- <br />--因为每个字符都大于7位，因此用11位编码： <br />--11000001 10000100 11000011 10100011 <br />--C1-- 84--　C3--　 A3 <br />--你会找到C1 84 C3 A3 -- <br />　　　　 <br />　　但是我们往往忽略掉这个参数，因此这样往往会有跨平台的问题： <br />　　--　　例３在中文平台上编译，生成ZhClass <br />　　--　　例３在英文平台上编译，输出EnClass <br />　　--1.　 ZhClass在中文平台上执行OK,但是在英文平台上不行 <br />　　--2.　 EnClass在英文平台上执行OK,但是在中文平台上不行 <br />　　原因： <br />　--1.在中文平台上编译后，其实str在运行态的char[]是0x4F60,　---- <br />　--在中文平台上运行，FileWriter的缺省编码是gb2312,因此 <br />　--CharToByteConverter会自动用调用gb2312的converter,把str转化 <br />　--成byte输入到FileOutputStream中，于是0xC4,0xE3放进了文件。 <br />　--但是如果是在英文平台下，CharToByteConverter的缺省值是8859_1, <br />　--FileWriter会自动调用8859_1去转化str,但是他无法解释，因此他会 <br />　--输出"?"　---- <br />　--2.　在英文平台上编译后，其实str在运行态的char[]是0x00C4 0x00E3,　---- <br />　--在中文平台上运行，中文无法识别，因此会出现?? <br />　--　　在英文平台上，0x00C4--&gt;0xC4,0x00E3-&gt;0xE3，因此0xC4,0xE3被放进了 <br />　--文件 <br /><img src ="http://www.blogjava.net/tony/aggbug/60666.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/tony/" target="_blank">tony-dl</a> 2006-07-28 22:55 <a href="http://www.blogjava.net/tony/articles/60666.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>