utf-8编码解析

java中InputStream、OutputStream读取以字节为单位,而Reader、Writer以字符为读写单位。下面例子模仿Reader直接读取utf-8格式编码字符:

public class Utf8Reader {
    private InputStream inputStream;
    //10000000取反
    private static int back10head=127;
    //11000000取反
    private static int back110head= 191;
    //11100000取反
    private static int back1110head= 223;
    //3个字节表示字符
    byte[] threeBytes = new byte[3];
    //2个字节表示字符
    byte[] twoBytes = new byte[2];
    public Utf8Reader(InputStream inputStream){
        this.inputStream=inputStream;
    }
    /**
     * 读取一个字符
     * @return
     * @throws IOException 
     */
    public int readChar() throws IOException{
        //读取一个字节
        int read = inputStream.read();
        //字节以1110开头,代表用3个字节表示一个字符
        if(read>=224){
            threeBytes[0]=(byte) read;
            //读取接下来的两个字节
            inputStream.read(threeBytes, 1, 2);
            //将3个字节转化为字符
            return parseThreeByte(threeBytes);
            //字节以110开头,便是用2个字节表示一个字符
        }else if(read>=192){
            twoBytes[0]=(byte) read;
            //读取接下来的一个季节
            inputStream.read(twoBytes, 1, 1);
            //将两个字节转化为字符
            return parseTwoByte(twoBytes);
            //字节以10开头,只能作为多字节字符中的一个字节,不能作为头部
        }else if(read>=128){
            throw new IOException("非法编码["+read+"]字符以10开头");
            //ASCII码或文件结束符-1,直接返回
        }else if(read>=0){
            return  read;
        }else{
            return  -1;
        }
    }
    
    /**
     * 将2个字节转化为1个字符
     * 将110xxxxx 10xxxxxx 字节数值转化为 xxxx xxxxxx 字符
     * @param twoBytes2
     * @return
     */
    private int parseTwoByte(byte[] bytes) {
        //去掉二字节头部表示
        int head=bytes[0]&back110head;
        //向右移6位
        head=head<<6;
        //去掉组成部分头部表示
        int tail=bytes[1]&back10head;
        return (char) (head|tail);
    }
    /**
     * 将三个字节转化为1个字符
     * 将1110xxxx 10xxxxxx 10xxxxxx字节数值转化为 xxx xxxxxx xxxxxx字符
     * @param threeBytes2
     * @return
     */
    private int parseThreeByte(byte[] bytes) {
        //去掉三字节头部表示
        int head=bytes[0]&back1110head;
        //向右移12位
        head=head<<12;
        //去掉组成部分头部表示
        int second=bytes[1]&back10head;
        int third=bytes[2]&back10head;
        //第二个字符向右移6位
        second=second<<6;
        return head|second|third;
    }
}
时间: 2024-10-22 10:41:36

utf-8编码解析的相关文章

字符串编码解析及字符编码输出

package 字符串编码解析; import java.io.UnsupportedEncodingException; public class Demo1 { public static void main(String[] args) throws UnsupportedEncodingException { String str = "中国"; //使用默认编码 byte[] gbk = str.getBytes("GBK"); //使用utf-8来编码

HTTP1.1中CHUNKED编码解析(转载)

HTTP1.1中CHUNKED编码解析 一般HTTP通信时,会使用Content-Length头信息性来通知用户代理(通常意义上是浏览器)服务器发送的文档内容长度,该头信息定义于HTTP1.0协议RFC  1945  10.4章节中.浏览器接收到此头信息后,接受完Content-Length中定义的长度字节后开始解析页面,但如果服务端有部分数据延迟发送吗,则会出现浏览器白屏,造成比较糟糕的用户体验. 解决方案是在HTTP1.1协议中,RFC  2616中14.41章节中定义的Transfer-E

scrapy gbk编码解析失败的问题

在使用scrpay 采集网易游戏网页时,遇到了编码失败的问题 http://play.163.com/17/0520/15/CKT0U63D00318PFI.html code_datas = byte.decode('gbk') 这里的'gbk'编码解析失败,查询原因得知,中文有三大编码,后面的标准是前面标准的扩展. GB2312 < GBK < GB18030 将命令换成 code_datas = byte.decode('GB18030') 后解析正常.

Python解析xml文件遇到的编码解析的问题

使用python对xml文件进行解析的时候,如果xml文件的头文件是utf-8格式的编码,那么解析是ok的,但如果是其他格式将会出现如下异常: xml.parsers.expat.ExpatError: unknown encoding 因此,为了保证程序的正常运行,我们需要对读取的文件进行编码处理. 1.首先将读取的字符从原来的编码解析,并编码成utf-8: 2.修改xml的encoding: 代码如下: import sys import os import datetime import

中国天气网 JSON接口的城市编码解析及结果

最近在弄一个Android应用,其中一个功能是天气情况展示,准备使用google的天气API服务(http://www.google.com/ig/api?hl=zh-cn&weather=,,,, ),不想这个接口已经在几个月前关闭服务了.于是各种资料,最终决定使用 中国天气网 的服务. 中国天气网提供有两种数据格式的接口: 一. XML接口 http://flash.weather.com.cn/wmaps/xml/china.xml http://flash.weather.com.cn/

Ben编码解析的C++实现

Ben编码的基本规则 B编码中有4种类型:字符串.整型.列表.字典. 字符串 字符串的编码格式为:<字符串的长度>:<字符串>,其中<>括号中的内容为必需.例如,有一个字符串spam,则经过B编码后为4:spam. 整型 整型的编码格式为:i<十进制的整型数>e,即B编码中的整数以i作为起始符,以e作为终结符,i为integer的第一个字母,e为end的第一个字母.例如,整数3,经过B编码后为i3e,整数?3的B编码为i?3e,整数0的B编码为i0e. 注意

Spring第七弹—依赖注入之注解方式注入及编码解析@Resource原理

    注入依赖对象可以采用手工装配或自动装配,在实际应用中建议使用手工装配,因为自动装配会产生未知情况,开发人员无法预见最终的装配结果. 手工装配依赖对象  手工装配依赖对象,在这种方式中又有两种编程方式 在xml配置文件中,通过在bean节点下配置,上边博客已经讲解,再次不在缀余. 在java代码中使用@Autowired或@Resource注解方式进行装配.但我们需要在xml配置文件中配置以下信息: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <be

编码解析

Unicode编码.ASCII码.UTF-8编码.GB2312编码分析总结 一.由简到繁顺序来总结: 1.ASCII编码: 在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态.一个字节(byte)共由八个二进制位来组成,共有256种状态,从 0000000到11111111. 阿拉伯数字.英文字母.标点符号等这些字符,怎么定义才能让计算机识别呢?因为计算机只识别二进制位0和1,所以以上这些字符就必须与二进制位(0和1)建立关系,才能让计算机识别. 6

iOS地址编码解析

- (void)viewDidLoad { [super viewDidLoad]; // 创建地址解析器 self.geocoder = [[CLGeocoder alloc] init]; } - (IBAction)encodeTapped:(id)sender { // 获取用户输入的地址字符串 NSString* addr = self.addrField.text; if(addr != nil && addr.length > 0) { [self.geocoder g