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