




免费预览已结束,剩余33页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
一 编码与乱码(01)-编码基础Unicode中文“艺”字: 827A二进制的“艺”字编码:1000 0010 0111 1010UTF-8的中文编码规则: 1110xxxx 10xxxxxx 10xxxxxxUTF-8的“艺”字编码: 1110【1000】 10【0010】【01】 10【11】【1010】UTF-8的转码过程解析: 8对应的1000被填入第一字节剩余的4位。2对应的0010被填入第2字节剩余的前4位。7对应的0111被拆开,前2位01被填入第2字节的后两位,后2位1被填入第3字节的前2位。A对应的1010被填入第3字节的后4位。UTF-8的最终编码结果:11101000-对应E8;10001001-对应89;10111010-对应BA。所以最终的UTF-8编码就是%E8%89%BAUnicode到UTF-8的转换:Unicode的16进制编码对应的2进制编码UTF-8规范的2进制编码UTF-8规范的16进制编码也就是说假如在Java的底层JVM,由于采用的是Unicode编码字符集,对“艺”字的编码是827A。那么在网络传输的过程中,我们当然不能直接传输827A这个字符过去代表艺”这个汉字,而必须要转换成0,1这样的字节流,才能在网络中传输。所以说UTF-8是一种为了方便网路传输,节省传输数量,而对Unicode的字符集的字符编号进行转换,从定长的2个字节(16进制)转换成13个的变长字节(2进制)表示的转换格式。由于Unicode采用的是2个字节的编码方式,而UTF-8转换后可能是13个字节,所以同一个汉字,在Unicode中的编码和经UTF-8转换后的编码值肯定是不同的。就好像艺字的Unicode编码是827A,经转换后的3个字节是E889BA。所以说对于英文字符来说,采用UTF-8对Unicode编码转换后节省了一倍的传输成本(由定长的2个字节变长1个字节),但对于原本双字节的东亚字符来说,反而增加了成本,是原来的1.5倍。小结:ASCII、GB2312、GBK、GB18030、Big5、Unicode都是字符集的名称。它们定义了采用12个字节的编码规范,为每个字符赋予了一个独一无二的编号。这个编号就是我们所说的“字符编码”。Unicode字符集定义的字符编码并不适合直接通过网络传输表达,因为它们必须转换成像0101这样的二进制字节流传输。所以就出现了不同的转换规范实现方式:UTF-8,TF-16等。这些不同的转换规范转换后的编码值和Unicode是不同的。对于UTF-8来说,它采用变长字节表示所有Unicode字符,对于英文来说和ASCII兼容,对于东亚字符来说,是原来传输成本的1.5倍。所以采用UTF-8编码转换方式虽然有利于统一,但增加了中文等双字节字符的传输成本。UTF-8采用首字节的高位1的个数表示字符的编码长度。例如在Unicode的编码规范中:汉字的表示区间为U-00000800至U-0000FFFF对应的UTF-8的转换规则为:1110xxxx 10xxxxxx 10xxxxxx 首字节3个1代表这个字符的编码长度为3个字节。如果是2个1则表示2个字节在底层的平台中如JVM,采用的是Unicode字符集,当要把这些字符通过网络传输时,可以选择通过UTF-8或其他(例如GB2312)编码转换方式对要传输的字符编码进行转换。如果目的端也是采用Unicode字符集,那么UTF-8转换后的编码可以被正常识别并解码成最终对应的Unicode字符集编号。如果是非Unicode字符集平台则可能出现乱码(UTF-8中汉字的3个连续字节被解析成GB2312的2个连续字节,出现丢失)。所以推荐在传输的两端采用Unicode字符集编码,在传输方式上采用UTF-8转换方式。javac命令是以系统默认编码读入源文件,然后按Unicode进行编码的。(备注:每个文件都有自己的编码,javac命令按照默认的文件编码读入,但是在将.java文件转换成.class的过程中,javac会将所有的字符转化成unicode的格式保存。)在运行时JVM也是采用unicode编码的,并且默认输入和输出使用的都是操作系统的默认编码。也就是说在new String(bytes,encode)中,系统认为输入的bytes是编码为encode的字节流(如果不指定encode,那么就是默认使用系统的编码方式),换句话说,如果按encode来翻译bytes才能得到正确的原始字符,这个字符最后要在java中保存,它还是要从这个encode转换成Unicode的。也就是说,假如我们需要从磁盘文件、数据库记录、网络传输一些字符,保存到Java的变量中,要经历由bytes-encode字符-Unicode字符的转换(例如new String(bytes, encode);而要把Java变量保存到文件、数据库或者通过网络传输,系统要做一个Unicode字符-encode字符-bytes的转换(例如String.getBytes(encode)二 编码与乱码(02)-String的getBytes(encoding)方法packageexample.encoding;importjava.io.UnsupportedEncodingException;/*TheClassGetBytesTest.*/publicclassGetBytesTest/*Themainmethod.*paramargsthearguments*/publicstaticvoidmain(Stringargs)Stringcontent=中文;StringdefaultEncoding=System.getProperty(file.encoding);StringdefaultLnaguage=System.getProperty(user.language);System.out.println(Systemdefaultencoding-+defaultEncoding);System.out.println(Systemdefaultlanguage-+defaultLnaguage);GetBytesTesttester=newGetBytesTest();bytedefaultBytes=tester.getBytesWithDefaultEncoding(content);tester.printBytes(defaultBytes);byteiso8859Bytes=tester.getBytesWithGivenEncoding(content,ISO-8859-1);tester.printBytes(iso8859Bytes);bytegbkBytes=tester.getBytesWithGivenEncoding(content,GBK);tester.printBytes(gbkBytes);byteutfBytes=tester.getBytesWithGivenEncoding(content,UTF-8);tester.printBytes(utfBytes);/*Getsthebyteswithdefaultencoding.*paramcontentthecontent*returnthebyteswithdefaultencoding*/publicbytegetBytesWithDefaultEncoding(Stringcontent)System.out.println(nEncodewithdefaultencodingn);bytebytes=content.getBytes();returnbytes;/*Getsthebyteswithgivenencoding.*paramcontentthecontent*paramencodingtheencoding*returnthebyteswithgivenencoding*/publicbytegetBytesWithGivenEncoding(Stringcontent,Stringencoding)System.out.println(nEncodewithgivenencoding:+encoding+n);trybytebytes=content.getBytes(encoding);returnbytes;catch(UnsupportedEncodingExceptione)e.printStackTrace();returnnull;/*Printsthebytes.*parambytesthebytes*/publicvoidprintBytes(bytebytes)for(inti=0;i1个字节,截取了一半的字节),所以转换后的结果是错误的。相同的平台下,同一个中文字符,在不同的编码方式下,得到的是完全不同的字节数组。这些字节数组有可能是正确的(只要该字符集支持中文),也可能是完全错误的(该字符集不支持中文)。记住:不要轻易地使用或滥用String类的getBytes(encoding)方法,更要尽量避免使用getBytes()方法。因为这个方法是平台依赖的,在平台不可预知的情况下完全可能得到不同的结果。如果一定要进行字节编码,则用户要确保encoding的方法就是当初字符串输入时的encoding。三 编码与乱码(03)-String的toCharArray()方法packageexample.encoding;importjava.io.UnsupportedEncodingException;/*TheClassGetCharTest.*/publicclassGetCharTest/*Themainmethod.*paramargsthearguments*/publicstaticvoidmain(Stringargs)Stringcontent=中文;StringdefaultEncoding=System.getProperty(file.encoding);StringdefaultLnaguage=System.getProperty(user.language);System.out.println(Systemdefaultencoding-+defaultEncoding);System.out.println(Systemdefaultlanguage-+defaultLnaguage);GetCharTesttester=newGetCharTest();tester.getCharWithDefaultEncoding(content);tester.getCharWithGivenEncoding(content,ISO-8859-1);tester.getCharWithGivenEncoding(content,GBK);tester.getCharWithGivenEncoding(content,UTF-8);/*Getsthecharwithdefaultencoding.*paramcontentthecontent*returnthecharwithdefaultencoding*/publicvoidgetCharWithDefaultEncoding(Stringcontent)System.out.println(nGetcharacterswithdefaultencodingn);printCharArray(content);/*Getsthecharwithgivenencoding.*paramcontentthecontent*paramencodingtheencoding*returnthecharwithgivenencoding*/publicvoidgetCharWithGivenEncoding(Stringcontent,Stringencoding)System.out.println(nGetcharacterswithgivenencoding:+encoding+n);tryStringencodedString=newString(content.getBytes(),encoding);printCharArray(encodedString);catch(UnsupportedEncodingExceptione)e.printStackTrace();/*Printsthechararray.*paraminStrtheinstr*/publicvoidprintCharArray(StringinStr)charcharArray=inStr.toCharArray();for(inti=0;iinStr.length();i+)byteb=(byte)charArrayi;shorts=(short)charArrayi;StringhexB=Integer.toHexString(b).toUpperCase();StringhexS=Integer.toHexString(s).toUpperCase();StringBuffersb=newStringBuffer();/printcharsb.append(char);sb.append(i);sb.append(=);sb.append(charArrayi);sb.append(t);/bytevaluesb.append(byte=);sb.append(b);sb.append(u);sb.append(hexB);sb.append(t);/shortvaluesb.append(short=);sb.append(s);sb.append(u);sb.append(hexS);sb.append(t);/UnicodeBlocksb.append(Character.UnicodeBlock.of(charArrayi);System.out.println(sb.toString();System.out.println(nCharacterslength:+charArray.length);【1】在中文平台下,测试的结果如下:System default encoding - GBKSystem default language - zhGet characters with default encodingchar0=中byte=45 u2Dshort=20013 u4E2DCJK_UNIFIED_IDEOGRAPHSchar1=文byte=-121 uFFFFFF87short=25991 u6587CJK_UNIFIED_IDEOGRAPHSCharacters length: 2Get characters with given encoding : ISO-8859-1char0=?byte=-42 uFFFFFFD6short=214 uD6LATIN_1_SUPPLEMENTchar1=?byte=-48 uFFFFFFD0short=208 uD0LATIN_1_SUPPLEMENTchar2=?byte=-50 uFFFFFFCEshort=206 uCELATIN_1_SUPPLEMENTchar3=?byte=-60 uFFFFFFC4short=196 uC4LATIN_1_SUPPLEMENTCharacters length: 4Get characters with given encoding : GBKchar0=中byte=45 u2Dshort=20013 u4E2DCJK_UNIFIED_IDEOGRAPHSchar1=文byte=-121 uFFFFFF87short=25991 u6587CJK_UNIFIED_IDEOGRAPHSCharacters length: 2Get characters with given encoding : UTF-8char0=?byte=-3 uFFFFFFFDshort=-3 uFFFFFFFDSPECIALSchar1=?byte=-3 uFFFFFFFDshort=-3 uFFFFFFFDSPECIALSchar2=?byte=-3 uFFFFFFFDshort=-3 uFFFFFFFDSPECIALSchar3=?byte=-3 uFFFFFFFDshort=-3 uFFFFFFFDSPECIALSCharacters length: 4【2】在英文平台下,测试的结果如下:System default encoding - Cp1252System default language - enGet characters with default encodingchar0=?byte=45 u2Dshort=20013 u4E2DCJK_UNIFIED_IDEOGRAPHSchar1=?byte=-121 uFFFFFF87short=25991 u6587CJK_UNIFIED_IDEOGRAPHSCharacters length: 2Get characters with given encoding : ISO-8859-1char0=?byte=63 u3Fshort=63 u3FBASIC_LATINchar1=?byte=63 u3Fshort=63 u3FBASIC_LATINCharacters length: 2Get characters with given encoding : GBKchar0=?byte=63 u3Fshort=63 u3FBASIC_LATINchar1=?byte=63 u3Fshort=63 u3FBASIC_LATINCharacters length: 2Get characters with given encoding : UTF-8char0=?byte=63 u3Fshort=63 u3FBASIC_LATINchar1=?byte=63 u3Fshort=63 u3FBASIC_LATINCharacters length: 2【结论】和getBytes(encoding)不同,toCharArray()返回的是自然字符。但是这个自然字符的数目和内容却是由原始的编码方式决定的。来看看里面是如何进行字符串的操作的:String encodedString = new String(content.getBytes(), encoding);char charArray = inStr.toCharArray();可以看到系统首先对原始字符串按照默认的编码方式进行编码,得到一个字节数组,然后按照指定的新的编码方式进行解码,得到新的编码后的字符串。再转换成对应的字符数组。由于在中文平台下,默认的字符集编码是GBK,于是content.getBytes()得到的是什么呢?就是下面这4个字节:byte0 = -42 hex string = ffffffd6byte1 = -48 hex string = ffffffd0byte2 = -50 hex string = ffffffcebyte3 = -60 hex string = ffffffc4如果新的encoding是GBK,那么经过解码后,由于一个字符用2个字节表示。于是最终的结果就是:char0=中 - byte0 + byte1char1=文 - byte2 + byte3如果新的encoding是ISO-8859-1,那么经过解码后,由于一个字符用1个字节表示,于是原来本应该2个字节一起解析的变成单个字节解析,每个字节都代表了一个汉字字符的一半。这一半的字节在ISO-8859-1中找不到对应的字符,就变成了?了,最终的结果:char0=? - byte0char1=? - byte1char2=? - byte2char3=? - byte3如果新的encoding是UTF-8,那么经过解码后,由于一个字符用3个字节表示,于是原来4个字节的数据无法正常的解析成UTF-8的数据,最终的结果也是每一个都变成?。char0=? - byte0char1=? - byte1char2=? - byte2char3=? - byte3如果是在英文平台下,由于默认的编码方式是Cp1252,于是content.getBytes()得到的字节都是被截去一半的残留字符,所以我们看到在英文平台下,不论指定的encoding是GBK、UTF-8,其结果和ISO-8859-1都是一样的。记住:这个方法再次证明了String的getBytes()方法的危险性,如果我们使用new String(str.getBytes(), encoding)对字符串进行重新编码解码时,我们一定要清楚str.getBytes()方法返回的字节数组的长度、内容到底是什么,因为在接下来使用新的encoding进行编码解码时,Java并不会自动地对字节数组进行扩展以适应新的encoding。而是按照新的编码方法直接对该字节数组进行解析。于是结果就像上面的例子一样,同样是4个原始字节,有些每2个一组进行解析,有些每个一组进行解析,有些每3个一组进行解析。其结果就只能看那种编码方式合适了。四 编码与乱码(04)-输出时的编码与乱码packageexample.encoding;importjava.io.BufferedWriter;importjava.io.File;importjava.io.FileNotFoundException;importjava.io.FileOutputStream;importjava.io.FileWriter;importjava.io.IOException;importjava.io.OutputStreamWriter;importjava.io.PrintWriter;importjava.io.UnsupportedEncodingException;importjava.io.Writer;importjava.nio.charset.Charset;importjava.util.Iterator;importjava.util.Set;importjava.util.SortedMap;/*TheClassIOEncodeTestisatesterclassforjavaencoding.Mainnalycontains*twoparts:*1.TestwrittenbyFileWriter,withorwithoutgivencharacterencodingvalue*2.TestwrittenbyOutputStreamWriter,withorwithoutgivencharacterencodingvalue*authorPaulLin*version1.0*/publicclassOutputEncodingTestprivatestaticStringword=Helloworld!中国;privatestaticfinalStringENCODING_EN=ISO-8859-1;privatestaticfinalStringENCODING_CN=GB2312;privatestaticfinalStringENCODING_UTF=UTF-8;privatestaticfinalStringDEFAULT_SYSTEM_ENCODING=System.getProperty(file.encoding);/*Themainmethod.*paramargsthearguments*/publicstaticvoidmain(Stringargs)OutputEncodingTesttester=newOutputEncodingTest();tester.testFileWriter();tester.testOutputStreamWriter();/*Testfilewriter.*/publicvoidtestFileWriter()/CreatetestresultfolderStringresultFolder=createResultFolder(System.getProperty(user.language),getBasePath();/WithdefaultplatformencodingwriteByFileWriter(word,resultFolder);/Withgivensystemfile.encodingpropertywriteByFileWriter(word,ENCODING_EN,resultFolder);writeByFileWriter(word,ENCODING_CN,resultFolder);writeByFileWriter(word,ENCODING_UTF,resultFolder);/*Testoutputstreamwriter.*/publicvoidtestOutputStreamWriter()/CreatetestresultfolderStringresultFolder=createResultFolder(System.getProperty(user.language),getBasePath();/WithdefaultplatformencodingwriteByOutputStreamWriter(word,resultFolder);/Withgivensystemfile.encodingpropertywriteByOutputStreamWriter(word,ENCODING_EN,resultFolder);writeByOutputStreamWriter(word,ENCODING_CN,resultFolder);writeByOutputStreamWriter(word,ENCODING_UTF,resultFolder);/*Printstheavailablecharset.*/publicvoidprintAvailableCharset()SortedMapcharsets=Charset.availableCharsets();SetcharsetKeys=charsets.keySet();System.out.println(nn);Iteratori=charsetKeys.iterator();while(i.hasNext()Stringkey=(String)i.next();Charsetcharset=(Charset)charsets.get(key);StringdisplayName=charset.displayName();booleancanEncode=charset.canEncode();System.out.println(key+-+displayName+-+canEncode);/*Writebyfilewriter.*paramcontentthecontent*/privatevoidwriteByFileWriter(Stringcontent,Stringdestination)StringdefaultEncoding=System.getProperty(file.encoding);System.out.println(Usingdefaultsystemencoding:+defaultEncoding);writeByFileWriter(content,defaultEncoding,destination);/*Writebyfilewriter.*paramcontentthecontent*paramencodingtheencoding*/privatevoidwriteByFileW
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- plc基础及应用考试试题及答案
- 电缆车间安全小知识培训课件
- 电线电缆绞丝工艺知识培训课件
- 电站操作规程培训课件
- 2.2做更好的自己 教案(表格式) 统编版道德与法治八年级上册
- 高电位活化细胞课件
- 高炉煤气安全知识培训课件
- LC-SF-14-生命科学试剂-MCE
- 2-Hydroxydihydrodaidzein-生命科学试剂-MCE
- Calindol-hydrochloride-13C-D2-生命科学试剂-MCE
- 药事管理学全套课件
- 社区心理学课件
- 《中式面点制作第二版》教案高教版
- 看门狗定时器
- 质量整改通知单(样板)
- 进展性脑卒中的诊疗策略课件
- 2020届高三北京高考“多文本阅读”总攻略
- (高职)中外民俗电子课件(全套)
- 《管理学基础》完整版课件全套ppt教程(最新)
- 新版《医疗器械监督管理条例》试题题库含答案
- 遵义县偏岩河工程设计说明书(鸭溪镇)
评论
0/150
提交评论