关于各种编码问题,汉字处理的一点小总结

本以为汉字编码是一个比较无聊的问题,但是经过昨天一天的探索和学习,发现其实这是一个蛮有意思的问题,在这个过程中我也学到了不少新的姿势,拿出来和大家分享一下。

首先必须是Unicode和UTF-8相互转来转去的问题,其实这个是有规律的,比如说汉字”吴“的Unicode编码为5434(16进制),那么它对于的二进制应该就是

0101 0100 0011 0100,接下来从后往前取6位,把它分成0101 0100 0011 0100,在截下来的前面补上10,就变成了1011 0100,继续这个步骤,把

0101 0100 00分为01010100 00,还是补上10,变成1001 0000,最后一段没到6位(0101),则说明该汉字用UTF-8存储需要3字节,故第一字节前四位为1110(三个字节所以三个1110,两个字节为两个110,一个字节只有0,UTF-8最多6个字节),所以第一个字节为1110 0101,把得到的三个字节,即111001011001 00001011 0100,转换成16进制,就是对应的UTF-8编码——E590B4。

从UTF-8换算成Unicode方法一样,只不过是倒推而已。比如”屋“的UTF-8编码为E5 B1 8B,先转成111001011011 00011000 1011,即其Unicode的二进制为

0101 1100 0100 1011,转成16进制,即5C4B。

前面将了一大堆,其实无非就是想说明,有目前计算机有多种编码方式,其中大家用的中文系统一般都是GBK编码的(GBK包括GB2312,来源请看昨天转载的文章),而目前主流最通用的编码方式为UTF-8,而UTF-8又是Unicode的一种实现

接下来是我今天发现的一个小问题,我发现Java在存储char的时候,不管你项目怎么设置,就算编译指定为UTF-8,也不能改变其对char的编码方式——Unicode,这也就是为什么我可以通过一下这段断码来判断该字符是否为汉字!

char word = '你';
String regEx = "[//u4e00-//u9fa5]";
assert Pattern.matches(regEx, String.valueOf(word));
由于时间关系,今天先接到这里,明天继续编辑,下面的代码是在写随机生成汉字时用到的,也是一个学习的过程,让我对Java IO有了更深刻的认识。
package nero.test;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

public class AlwaysTest {

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		String filePath = ".\\surname1.txt";
		File file = new File(filePath);
		
		FileInputStream fin = new FileInputStream(file);
		BufferedInputStream bin = new BufferedInputStream(fin);
		//读取文本文件头信息,判断文本文件为哪种类型的编码方式
		int code = (bin.read() << 8) + bin.read();
		String codeType = null;
		switch (code) {
			case 0xefbb:
				codeType = "UTF-8";
				break;
			case 0xfffe:
				codeType = "Unicode";
				break;
			case 0xfeff:
				codeType = "UTF-16BE";
			default:
				codeType = "GBK";
		}
		bin.close();
		fin.close();
		fin = new FileInputStream(file);
		InputStreamReader reader = new InputStreamReader(fin, codeType);
		BufferedReader bufferedReader = new BufferedReader(reader);
		
		String regEx = "[\\u4e00-\\u9fa5]"; // 汉字Unicode范围
		List<String> subname = new ArrayList<String>();
		int temp;
		/*
		 * 这一个循环其实非常有意思
		 * 开始文件是以UTF-8读入的
		 * 但是这里转成char后,得到的却是Unicode的编码
		 * 我的项目编码方式也是UTF-8,这就说明数据在被读入的时候进行了转码运算
		 * 怀疑是InputStreamReader做的,因为它是按照字符来读入的(注意是字符,不是字节)
		 * 为了证明这一结论,输出了temp的值,其中汉字“李”的输出值为26446,上网查其Unicode为674E
		 * 两值正好相等,证明了结论,同时也印证了Java中char都是按照Unicode编码存储的!
		 */
		while ((temp = bufferedReader.read()) != -1) {
			System.out.println(temp);
			char word = (char) temp;
			if (Pattern.matches(regEx, String.valueOf(word))) subname.add(String.valueOf(word));
		}
		
		bufferedReader.close();
		reader.close();
		fin.close();
		for (int i = 0; i < subname.size(); i++) {
			System.out.println("surname[" + i + "] = \"" + subname.get(i) + "\";");
		}
		System.out.println(subname.size());
	}

}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值