问题:
使用字节流读取文本文件时,会将一个汉字劈成两半,一次只能读一半出来,产生了乱码,无法使用。就算是一次读取2个字节出来,也依然不能解决问题。
如何解决乱码问题,读出完整的汉字和中英文混杂的整篇文章呢?
- char型变量是用来存储Unicode编码的字符的,unicode编码字符集中包含了汉字,所以,char型变量中当然可以存储汉字啦。所有字符均以2个字节存储。
- 这个方法使用一个byte的数组作为一个缓冲区,每次从数据源中读取和缓冲区大小(二进制位)相同的数据并将其存在缓冲区中。当然byte数组中存放的仍然是0-255的整数,将二进制转换为十进制这个过程仍然是read方法实现的。
- 当然byte数组中存放的仍然是0-255的整数,将二进制转换为十进制这个过程仍然是read方法实现的。
- 需要注意的是,虽然我们可以指定缓冲区的大小,但是read方法在读取数据的时候仍然是按照字节来读取的。在utf-8等变长编码中,一个复杂字符(比如汉字)所占字节往往大于1,并且长度往往是不固定的。(参照UTF-8编码规则)按照字节读取数据会将字符割裂,这就导致我们在使用read(byte[] b)方法读取文件时,虽然指定了缓冲区的大小,但是仍然会出现乱码。
解决办法 :先读一个字节出来,判断是否是双字节字符(如汉字)的一半,如果是,就再读一个字节进来。然后,将两次读取的内容组装在一起,就是一个完整的汉字了。就算是有多字节的,未来也是可以照此思路解决的。
关键代码 如下:
byte [] bytes1=new byte[1]; //创建英文数组,准备接收字符串,存放1个字节
byte [] bytes2=new byte[2]; //处理中文,准备接收字符串,存放2个字节(双字节)if (fis.available()!=-1){ //如果多次读取,要用while,此处从简
int size=0;
int j= 0; //第几次读取
while ((size = fis.read(bytes1))!=-1){
j++; //读取次数
sBytes = new String(bytes1);
//如果读取到的bytes[0]<0,说明是中文的半个字符,则再读取一个字节进来
if (bytes1[0]<0){
bytes2[0]=bytes1[0];
fis.read(bytes1);
bytes2[1]= bytes1[0];
sBytes = new String(bytes2);//重新组装
}
sAll=sAll + sBytes; // sAll:文件的总内容
System.out.println("第"+j+ "次,内容sBytes:"+ sBytes+ "\t"+ "size:"
+ size+ "\t"+ bytes1[0]); // (char)bytes[0]
}