在java中读取字符串时,不可避免的遇到处理汉字的问题,而汉字乱码也是我们最常遇到的问题。
一、首先,我们先分析下java中字符串的存储规则。
与其它语言一样,java中的String实际上是一个char数组,在java中,一个char占16位也就是2个字节。所以可以表示0-65535种不同数据。
在java中,字符的显示是通过一个叫字符集的东西的,简单来说,就是一个序列(可能是一个,也可能是多个)的字节惟一地对应某个特定的符号(如汉字等)。
例如:GBK字符集中,两个相临字节:184 181表示人。97字节表示字符a;而在UTF-8编码中,156 198 198三个相临字节表示人字。一个字节97即表示a;
在java中,我们默认使用的字符集是GBK,当然,你也可以通过自己动手来改变使用的字符集,方法有以下三种:(以改变成"x-MacThai"字符集为例)
(1).Properties pps=System. getProperties();
pps.put("file.encoding","x-MacThai");
//设置完成后要将属性保存
System.setProperties(pps);
(2).System.setProperty("file.encoding","x-MacThai");
(3).运行时设置 java -D file.encoding=x-MacThai
二、其次,我们来讨论下我们出现汉字乱码问题的原因。
我们先来分析下我们在传输、或者在文件读写时的操作,我们常使用的是out.write(string.getBytes())的方法来讲我们需要的字符数据行输出。在默认情况下,getBytes方法是对字符串按照GBK格式进行解析的,即:一个字符串str=”a人”那么它解析后即变为”97 184 181”。
再来看看我们读入数据的操作,如果我们使用了读取整个比特流放入一个比特数组中,再将它以GBK的格式转化为字符串的话自然没有问题,可是如果我们如果使用了每读到一个字节就将它转化为一个字符加入字符串的话那么将必然会出问题,就以上面的str=”a人”为例,它输出的比特流为:97 184 181 而当你读到97时将它转为字符’a’后加到字符串中,这当然没问题,可是再往后看,读到184,程序还是会直接将它转为对应的字符,那么自然,问题就出来了,它只能对应出”?”,同样,字符181也只能对应出”?”,因而读到的字符串就变为也”a??”,这自然不是我们想要的结果。
三、最后,让我们讨论来如何解决问题吧,自然可以看出,是由于我们在读取数据字符流时转换到字符时出了问题,就是在转换汉字时,本应是由两个字符转成一个汉字的我们却对这两个字符分别做了处理。
下面我们来写一个算法来实现这个问题的解决吧!(以GBK为例)
(1)输出流部分:
str=”a人”
在这里,我们只需要将数据流按一定的字符集输出即可。
out.write(str.getBytes(“GBK”));
注:java中默认的是GBK字符集,所以这里不写也没关系。
(2)读取数据部分:
查询GBK字符集的规则可知道,为了区分汉字与英文字符,GBK中若读到的一个字节为<128,那么它表示一个英文字符或是符号,反之则为一个汉字。 知道规则后,我们便很好来设计算法了。
1> 读取一个字节数据。
2> 若它小于128,则直接将其以GBK字符集转为字符,加入到输出字符串中。 转第一步。
3> 若它大于等于128再读取一个字节数据,将它们一起以GBK字符集转为字符,加入到输出字符串中。转第一步。
四、小结:关于汉字,有许多的字符集可供使用,这里给大家一个链接供大家参考。
http://baike.baidu.com/view/51987.htm
一、首先,我们先分析下java中字符串的存储规则。
与其它语言一样,java中的String实际上是一个char数组,在java中,一个char占16位也就是2个字节。所以可以表示0-65535种不同数据。
在java中,字符的显示是通过一个叫字符集的东西的,简单来说,就是一个序列(可能是一个,也可能是多个)的字节惟一地对应某个特定的符号(如汉字等)。
例如:GBK字符集中,两个相临字节:184 181表示人。97字节表示字符a;而在UTF-8编码中,156 198 198三个相临字节表示人字。一个字节97即表示a;
在java中,我们默认使用的字符集是GBK,当然,你也可以通过自己动手来改变使用的字符集,方法有以下三种:(以改变成"x-MacThai"字符集为例)
(1).Properties pps=System. getProperties();
pps.put("file.encoding","x-MacThai");
//设置完成后要将属性保存
System.setProperties(pps);
(2).System.setProperty("file.encoding","x-MacThai");
(3).运行时设置 java -D file.encoding=x-MacThai
二、其次,我们来讨论下我们出现汉字乱码问题的原因。
我们先来分析下我们在传输、或者在文件读写时的操作,我们常使用的是out.write(string.getBytes())的方法来讲我们需要的字符数据行输出。在默认情况下,getBytes方法是对字符串按照GBK格式进行解析的,即:一个字符串str=”a人”那么它解析后即变为”97 184 181”。
再来看看我们读入数据的操作,如果我们使用了读取整个比特流放入一个比特数组中,再将它以GBK的格式转化为字符串的话自然没有问题,可是如果我们如果使用了每读到一个字节就将它转化为一个字符加入字符串的话那么将必然会出问题,就以上面的str=”a人”为例,它输出的比特流为:97 184 181 而当你读到97时将它转为字符’a’后加到字符串中,这当然没问题,可是再往后看,读到184,程序还是会直接将它转为对应的字符,那么自然,问题就出来了,它只能对应出”?”,同样,字符181也只能对应出”?”,因而读到的字符串就变为也”a??”,这自然不是我们想要的结果。
三、最后,让我们讨论来如何解决问题吧,自然可以看出,是由于我们在读取数据字符流时转换到字符时出了问题,就是在转换汉字时,本应是由两个字符转成一个汉字的我们却对这两个字符分别做了处理。
下面我们来写一个算法来实现这个问题的解决吧!(以GBK为例)
(1)输出流部分:
str=”a人”
在这里,我们只需要将数据流按一定的字符集输出即可。
out.write(str.getBytes(“GBK”));
注:java中默认的是GBK字符集,所以这里不写也没关系。
(2)读取数据部分:
查询GBK字符集的规则可知道,为了区分汉字与英文字符,GBK中若读到的一个字节为<128,那么它表示一个英文字符或是符号,反之则为一个汉字。 知道规则后,我们便很好来设计算法了。
1> 读取一个字节数据。
2> 若它小于128,则直接将其以GBK字符集转为字符,加入到输出字符串中。 转第一步。
3> 若它大于等于128再读取一个字节数据,将它们一起以GBK字符集转为字符,加入到输出字符串中。转第一步。
四、小结:关于汉字,有许多的字符集可供使用,这里给大家一个链接供大家参考。
http://baike.baidu.com/view/51987.htm