java的io流基础篇乱码的原因

1.编码的产生:我们的存储的基本单元是一个byte字节,然而人类的语言太多,无法用一个基本单元来表示,然而为了拆分或者一些相应的翻译工作,导致了编码的产生

2.常见的编码格式

ASCll :用一个字节的低7位共128个来表示,0-31表示控制字符,32-126表示打印字符, ASCll的二进制第一位也就是最高位,目的是用来做奇偶检验的,所谓奇偶校验,是指在代码传送过程中用来检验是否出现错误的一种方法,一般分奇校验和偶校验两种。奇校验规定:正确的代码一个字节中1的个数必须是奇数,若非奇数,则在最高位添1;偶校验规定:正确的代码一个字节中1的个数必须是偶数,若非偶数,则在最高位添1;看到这是似乎对奇偶检验还是较为模糊,不大明白,例如字母A的ASCII码为1000001,若使用偶校验的结果是:01000001,奇检验的结果是11000001;奇偶检验是事先设定好了的,当CPU读取存储的数据时,它会再次把前8位中存储的数据相加,计算结果是否与校验位相一致。从而一定程度上能检测出内存错误,奇偶校验只能检测出错误而无法对其进行修正,同时虽然双位同时发生错误的概率相当低,但奇偶校验却无法检测出双位错,检验到错误的时候,接收数据方就会要求发送方重新传数据

范例:

串行数据在传输过程中,由于干扰,可能使位变为1,(为什么不变0?脉冲)这种情况,称为出现了"误码"。传输中的错误,叫"检错"。发现错误后消除错误叫"纠错"。最简单的检错方法是"奇偶校验",一般在同步传输方式中常采用奇校验,而在异步传输方式中常采用偶校验

ISO-8859-1:由于128字符不够用,于是ISO组织在ASCll的基础上制定一系列的标准来拓展ASCll编码(ISO-8859-1~ISO-8859-15),ISO-8859-1也是作为java web中默认的解析方式

GB2312:全称是《信息交换用汉字编码字符奇基本集》,占两个字节,其中A1~A9是符号区,B0~F7是汉字区

GBK:全称《汉字内码拓展规范》,是对GB2312的拓展,它的编码是与GB2312相兼容的,也就是说用GB2312编码的汉字可以用GBK来编码而不会乱码

GB18030:我国强制标准,可能是单字节 双字节 四个字节,与GB2312编码是兼容的,我国标准,但是使用并不广泛

UTF-16:定义了Unicode(世界上所有的语言都可以用这本字典来相互翻译,是java和xml的基础)在计算机中的存取方法,用两字节来表示Unicode的转换格式,在表示上相对来说简单方便,但是相对于UTF-8来内存空间增大了很多

UTF-8:对每个编码区域有不同的字码长度,不同类型字符可以有1-6个字节组成

UTF-8的编码原则:

如果是一个字节,最高位为0,

如果一个字节以11开头,表示相应的首字节

如果以10开始,则表示他不是首字节,需要向前查找才能得到当前字符的首字符

例如:

1字节 0xxxxxxx

2字节 110xxxxx 10xxxxxx

3字节 1110xxxx 10xxxxxx 10xxxxxx

4字节 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

5字节 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

6字节 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

说明:UTF-8用来表示字符编码的实际位数最多有31位,即上表中x所表示的位。除去那些控制位(每字节开头的10等),这些x表示的位与UNICODE编码是一一对应的,位高低顺序也相同。 将UNICODE转换为UTF-8编码时应先去除高位0,然后根据所剩编码的位数决定所需最小的UTF-8编码位数(ASCll标准编码为7位)。

3.io流的编解码

 1)读取文件

假如是采用的ascii写的那么不会产生乱码(这也是unicode(\u5F20\u4E09的形式写的转换成任意编码(在能识别的情况下都不会乱码))),假如使用其他编码编写(这里假如是utf-8)文件,在java在没有设置解码的时候,java会默认的按照(gbk)来解码成unicode码(java的jvm就会gbk来解析成utf-16存储),而我们的源文件是使用utf-8写的,所以导致乱码,所以在使用的时候我们会指定按照指定的编码集来解码保证争取的unicode(Char)保存方式,以便的到正确的编解码,在本地文件可以使用EncodingDetect  jar包来获取,这是利用统计学得出的结论,并不是百分百正确,但是准确率在百分之99以上,网络爬虫可以使用cpdetector_1.0.10.jar,同样也是基于统计学

实例

     //简写EncodingDetect的使用方法
     String pathname = "F:/test/file1/file2.txt"; //获取编码格式 String encode = EncodingDetect.getJavaEncode(pathname);
     System.
out.println(encode);     
EncodingDetect.readFile(pathname, encode);
//cpdetector网络爬虫获取编码的方法   
public static String getFileEncode(String path) { /* * detector是探测器,它把探测任务交给具体的探测实现类的实例完成。 * cpDetector内置了一些常用的探测实现类,这些探测实现类的实例可以通过add方法 加进来,如ParsingDetector、 * JChardetFacade、ASCIIDetector、UnicodeDetector。 * detector按照“谁最先返回非空的探测结果,就以该结果为准”的原则返回探测到的 * 字符集编码。使用需要用到三个第三方JAR包:antlr.jar、chardet.jar和cpdetector.jar * cpDetector是基于统计学原理的,不保证完全正确。 */ CodepageDetectorProxy detector = CodepageDetectorProxy.getInstance(); /* * ParsingDetector可用于检查HTML、XML等文件或字符流的编码,构造方法中的参数用于 * 指示是否显示探测过程的详细信息,为false不显示。 */ // detector.add(new ParsingDetector(false)); /* * JChardetFacade封装了由Mozilla组织提供的JChardet,它可以完成大多数文件的编码 * 测定。所以,一般有了这个探测器就可满足大多数项目的要求,如果你还不放心,可以 * 再多加几个探测器,比如下面的ASCIIDetector、UnicodeDetector等。 */ detector.add(JChardetFacade.getInstance());// 用到antlr.jar、chardet.jar // ASCIIDetector用于ASCII编码测定 // detector.add(ASCIIDetector.getInstance()); // UnicodeDetector用于Unicode家族编码的测定 // detector.add(UnicodeDetector.getInstance()); java.nio.charset.Charset charset = null; File f = new File(path); try { charset = detector.detectCodepage(f.toURI().toURL()); } catch (Exception ex) { ex.printStackTrace(); } if (charset != null) return charset.name(); else return null; };

4.url的编解码原则在web核心中写

猜你喜欢

转载自www.cnblogs.com/gg128/p/9346589.html
今日推荐