由于很需要转来--------二进制字符流读取,判定单字节英文标点字符和双字节中文---防止乱码

博客讲述了在处理二进制数据流时遇到的乱码问题,特别是如何在GBK编码下正确识别单字节英文字符和双字节中文字符。作者分享了解决方案,通过判断字节来防止因字节流截断导致的乱码现象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


说明:尽信书不如无书,网上的东西本来就是精华糟粕都有的,下面这篇文章是我在做二进制数据流读取时参考的一篇文章,怎么做都有错误,不知道是哪里的问题,以为是自己的逻辑问题检查了很多遍,在自己静下心来想想的时候才发现,原来自己犯了多么严重的错误,英文的半角字符就是ASCII的那128个,这里的意思就是GBK把英文半角的128个字符放在了首部,显然文章中提示给了我应该是最起始的128个字符,而我却不知其根本而按照错误的0-0x40去判定单字节的英文字符,128显然它的编码应该是:0x00-0x80这是对自己的一次教训,也一次记录下来勉励以后。------正确结论:在读取二进制字节流的时候常常会出现乱码,这是因为同一个流中会有半角英文字符和除此以外其他的字符如中文字符。显然他们所占的字节数是不同的,在逐个读取的过程中,如何区分开来这些编码从而用不同的方式提取是一个大问题,这是我写的一个字符提取输出代码段。从其中能够看出窍门。我们可以把一位的英文字母提取出之后,对其余的中文全角字符做两位一提取两位一输出。,即可得到解析的正确结果。

			for (l = 0; l <k-1; l++) {//这里的帧校验字段用的2位
				c = (int)recData[l];
				nCheck=checkCRC(nCheck, c);
				if (recData[l]!=(byte)0x00) {//填充字节0x00
					nCount--;
					if (recData[l]>0 && recData[l]<0x80) {
						System.out.print(new String(recData,l,1,"GBK"));
					}else {
							System.out.print(new String(recData,l,2,"GBK"));
							l++;
							c = (int)recData[l];
							nCheck=checkCRC(nCheck, c);
					}


转载请注明出处

下面文章出处:http://blog.youkuaiyun.com/zhouxiaoli521/article/details/5457468


GBK为双字节编码,但是他向下兼容gb2312,也就是说英文标点符号、字母、数字都是用一个字节标示。

我现在有这样的需求:我需要读取一个被加密的文本文件。

现在有两个限制,第一我不能一次读取整个文本,因为文本很大,手机不能承受。第二,因为这个文件加密是对每个字节做的处理,所以我必须先用字节流读取这个文件并解密在转换成字符。

我第一次用字节流读取一段内容时,最后一个字节可能是一个中文字符的前半个字节。如果不做任何处理就显示出来,第一次是最后一个字是乱码,然后继续读继续显示,后面就有大段乱码。 一下个图就是最好的说明

“一束驱魔光环落在了奇迹古树上,死亡缠绕被解除,然而”

我每次读取固定的长度,一上图为例每次读取16个字节,第一次读取没问题,第二次读取的时候,因为“,”只占一个字节,所以这次读取的末尾字节是“亡”字的高字节,这半个字节无法被正确编码,所以被“?”代替,当我在读第三次的时候,原本“B2 F8”的“缠”字,却按“F6 B2”来编码,这样后面的内容就全乱了。

 

要解决这个问题,我就必须要判断最后一个字节是不是高字节。因为如果末尾是低字节和单字节对我后面的操作都没有影响。

在字节流中判断,我目前还没找到方法,所以我在字符中判断

我把每次读取的一段字节解密后,转成字符new String(_data,"GBK").toCharArray();

然后在判断最后一个字符是否为65533,因为如果用半个字节去转成GBK的字符是转不了的,所以就会用65533来代替这个无法处理的字符。

判断之后把这半个字节保存来下放到下次读取的数据前,在一起转成字符就可以了


 

===============================更新===========================================

上面这个方法只能在模拟器上实现,在真机上不可以,因为在真机上,如果在末尾有半个字节,它会自动去掉,我用N73做个测试所以可以肯定,一下是我的解决办法,这个方法在真机上测试没有问题

 

我需要读取一个文件,但是不能一次加载,只能分段读取,我已经解决了。
首先你需要知道GBK编码范围:首字节:0x81~0xFE;尾字节:0x40~0xFE
出现乱码的原因就是截取的位置不对 导致一个尾字节+高字节组合成一个汉字 
所以 我们需要判断第一个字节或者最后一个字节是否是高字节 就能解决这个问题
根据GBK编码范围 我们可以肯定2点
1:0<X<0x40 肯定是标点或其它单字节字符
2:X<0x81||X>0x40 肯定是低字节
如果 X>0x81 有可能是高字节也有可能是低字节
因此 我们可以向后一个(X-1)(或者前一个(X+1)都一样)字节去查找 判断它是什么字节
如果后一个(X-1)字节是标点或者低字节 则X肯定是高字节
如果后一个(X-1)也是高字节则一直查找下去

这样判断下来就可以避免 编码时出现乱码的问题了


 public boolean charCompare(byte[] str){
  boolean bln=false;
  int i=str.length-1;
  int j=0;
  System.out.println("File.charCompare() 【"+str[i]+"】");
   if((str[i]>0&&str[i]<0x40)){
    System.out.println("File.charCompare() 【标点】【"+str[i]+"】");
   }else if((str[i]<0&&str[i]<-127)||str[i]>64){
    System.out.println("File.charCompare() 【低字节】【"+str[i]+"】");
   }else {  
    while(str[i-1]<0&&str[i-1]>-127){
     System.out.println("File.charCompare() 【向前找】【"+str[i-1]+"】");
     j++;
     i--;
    }
    System.out.println("File.charCompare() 【找完】【"+str[i-1]+"】["+j+"]");
    if(j%2==0)
     return bln=true;   
   }
  return bln;
 }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值