如果可以的话,
String old = "中文的";
String u8 = new String(old.getBytes("gbk"),"utf-8");
String gb = new String(u8.getBytes("utf-8"),"gbk");
System.out.println(u8);
System.out.println(gb);//会乱码
思路错在哪里
13 个解决方案
#1
不行。
因为对UTF-8合法的字节数组可能对GB不合法,反之也一样。
即,UTF-8和GB不是二进制相容的。
GB和ISO-8859-1可以这样互转,它们是二进制相容的。
因为对UTF-8合法的字节数组可能对GB不合法,反之也一样。
即,UTF-8和GB不是二进制相容的。
GB和ISO-8859-1可以这样互转,它们是二进制相容的。
#2
refer to this:
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
public class Test {
public static void main(String[] args) {
String str = "测试字符转换 hello word"; //默认环境,已是UTF-8编码
try {
String strGBK = URLEncoder.encode(str, "GBK");
System.out.println(strGBK);
String strUTF8 = URLDecoder.decode(str, "UTF-8");
System.out.println(strUTF8);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
#3
And:
The results:
import java.io.UnsupportedEncodingException;
public class Test {
public static void main(String[] args) throws UnsupportedEncodingException {
String old = "测试字符转换 ";//默认环境,已是UTF-8编码
String gb = new String(old.getBytes("UTF-8"), "GBK");
System.out.println(""+gb);
String u8 = new String(gb.getBytes("GBK"), "UTF-8");
System.out.println(u8);// 没有乱码
}
}
The results:
娴嬭瘯瀛楃杞崲
测试字符转换
#4
谢高手.
utf8应该包含"中文的"这样的中文吧,虽然编码位置不同于gb。
"UTF-8和GB不是二进制相容",我理解String(old.getBytes("gbk"),"utf-8")是将gbk的二进制转换成utf8相应的二进制,不知理解错在哪
#5
public static void main(String[] args) throws Exception{
String old = "中文的";
String s1 = new String(old.getBytes("gbk"),"iso-8859-1");
String s2 = new String(s1.getBytes("iso-8859-1"),"gbk");
System.out.println(s1);
System.out.println(s2);//中文的
String str = new String(old.getBytes("gbk"),"gbk");
System.out.println(str);//中文的
}
#6
不知道你在问什么。你的代码有任何可能正确的理由值得你来发帖问错在哪里?
#7
说说我的理解吧,java的String在内存中是一直的编码为utf-8的,在你声明了String之后,它在内存中就是utf-8了,你输出至控制台时,虚拟机根据本地的环境编码等因素转化为字节流,然后把这些字节流扔给操作系统,由操作系统负责打印到控制台还是输出至文件
所以我认为lz的转化为字节码之后由转为String,这步实际只是在解码+编码之后,同一存为了utf-8,jvm的内存中的统一编码方式
下面的代码,lz看看,可能有点帮助
output:
utf8:
e4 b8 ad e6 96 87 e7 9a 84 20 61 62 63 64
gbk:
d6 d0 ce c4 b5 c4 20 61 62 63 64
中文的 abcd
中文的 abcd
在这里可以看出utf-8和gbk编码的汉字编码
所以我认为lz的转化为字节码之后由转为String,这步实际只是在解码+编码之后,同一存为了utf-8,jvm的内存中的统一编码方式
下面的代码,lz看看,可能有点帮助
String old = "中文的 abcd";
byte [] utf8Decode = old.getBytes("utf-8");
System.out.println("utf8:");
for (byte b: utf8Decode) {
System.out.print(Integer.toHexString(b & 0xFF));
System.out.print(" ");
}
System.out.println();
byte [] gbkDecode = old.getBytes("gbk");
System.out.println("gbk:");
for (byte b: gbkDecode) {
System.out.print(Integer.toHexString(b & 0xFF));
System.out.print(" ");
}
System.out.println();
System.out.println(new String(utf8Decode,"utf-8"));
System.out.println(new String(gbkDecode,"gbk"));
output:
utf8:
e4 b8 ad e6 96 87 e7 9a 84 20 61 62 63 64
gbk:
d6 d0 ce c4 b5 c4 20 61 62 63 64
中文的 abcd
中文的 abcd
在这里可以看出utf-8和gbk编码的汉字编码
#8
new String(old.getBytes("gbk"),"utf-8")是将中文字符串的GBK二进制编码 强制认作UTF-8二进制编码,尝试得到中文,当然不会如愿以偿。
#9
在这个帖子的 11 楼中我有详尽的回复,有兴趣的话可以去看看:
求一字符串x
http://topic.csdn.net/u/20080623/16/e0f44f00-eaf9-4d38-b325-a3cc443f2ec9.html
求一字符串x
http://topic.csdn.net/u/20080623/16/e0f44f00-eaf9-4d38-b325-a3cc443f2ec9.html
#10
简单给你解释下错在哪里.
#11
首先,楼主是知道的,Java中(JVM)字符串、字符 用的是Unicode, 这是Java的标准编码。像'中'用4E2D(16进制)表示。
其次,楼主也知道,世界很大,有很多的语言文字;也知道计算机只识别由0、1组成的代码;这里只说汉字和英文;
美国有个“美国信息交换标准编码”,即ASCII码,ASCII码是英文信息处理的标准编码,用些数字来代表字符,如'A'用数字65表示;
汉字信息处理也必须有一个统一的标准编码,中国是“*国家标准信息交换用汉字编码”,简称“国标”,国标表把七千余汉字、以及标点符号、外文字母等用一些数字来代表,如'中'用5448区位码表示;
这里就是ASCII码表:http://cs.scu.edu.cn/~guobing/c_lan/ppt/ASCII.pdf
这里就是国标区位码表:http://www.xaipe.edu.cn/xwfb/newsfile/20061218120842.doc
Unicode码表请查看官网。
但是处理不同的标准是痛苦的,如汉语,*有一个Big5编码标准,很多编码和国标是相同的,为了解决中文问题,不能从扩展ASCII的角度入手,也不能仅靠中国一家来解决。而必须有一个全新的编码系统,这个系统要可以将中文、英文、法文、德文……等等所有的文字统一起来考虑,为每个文字都分配一个单独的编码,这样才不会有上面那种现象出现。于是,Unicode诞生了。
以上就是我们说的字符集,下面简单说下字符集编码:
Java中Unicode用两个字节表示(UCS-2),但只规定了怎么用多个字节表示各种文字,怎样传输这些编码,这就是由UTF(UCS Transformation Format)规范规定的,常见的UTF规范包括UTF-8、UTF-16等,这就是字符集编码;这里只说UTF-8:
UTF-8用1到6个字节编码UNICODE字符。如果Unicode字符由2个字节表示,则编码成UTF-8很可能需要3个字节,UFT-8转换表表示如下:
UNICODE UTF-8
0000 - 007F 0xxxxxxx
0080 - 07FF 110xxxxx 10xxxxxx
0800 - FFFF 1110xxxx 10xxxxxx 10xxxxxx
如'中'的Unicode是 4e2d,显然落在了0800 - FFFF 区,就用三个字节表示:11100100 10111000 10101101; 就是把4e2d转换成2进制0100 1110 0010 1101,依次填入XXX符号就行了。
国标码,全称是GB2312-80, 要理解国标码,楼主得先理解 区位码、国标码与机内码的关系;简单说下:
(1)区位码先转换成十六进制数表示
(2)区位码(十六进制)+2020H=国标码(十六进制);(两位两位相加)
(3)国标码(十六进制)+8080H=机内码(十六进制); (两位两位相加)
国标码是不可能在计算机内部直接采用的,与ASCII码发生冲突,如'保' 字,国标码为31H和23H,而西文字符“1”和“#”的SCII也为31H和23H,现假如内存中有两个字节为31H和23H,;这到底是一个汉字,还是两个西文字符“1”;和“#”? 于是就出现了二义性.
所以是用机内码表示的,其实就是GBK编码,该编码标准兼容GB2312;
还说下区位码的来由:
国标码汉字及符号组成一个94行94列的二维代码表中。在此方阵中,每一行称为一个"区",每一列称为一个"位"。这个方阵实际上组成一个有94个区(编号由01到94),每个区有94个位(编号由01到94)的汉字字符集。每两个字节分别用两位十进制编码,前字节的编码称为区码,后字节的编码称为位码,此即区位码,其中,高两位为区号,低两位为位号。这样区位码可以唯一地确定某一汉字或字符;反之,任何一个汉字或符号都对应一个唯一的区位码,没有重码。
由上面的关系可以知道: 机内码(十六进制) = 区位码(十六进制) + A0A0H;
如'中'的区位码是5448,表示的是'中'在54区,48位,GBK怎样编码呢?如下:
5448的十六进制是3630;
3630 + A0A0 = D6D0;
D6D0就是GBK编码了;
这里有个编码表查询 http://blog.csdn.net/boliu218/archive/2011/01/06/6119710.aspx;
说了这么多,以下不说楼主也基本明白了。
其次,楼主也知道,世界很大,有很多的语言文字;也知道计算机只识别由0、1组成的代码;这里只说汉字和英文;
美国有个“美国信息交换标准编码”,即ASCII码,ASCII码是英文信息处理的标准编码,用些数字来代表字符,如'A'用数字65表示;
汉字信息处理也必须有一个统一的标准编码,中国是“*国家标准信息交换用汉字编码”,简称“国标”,国标表把七千余汉字、以及标点符号、外文字母等用一些数字来代表,如'中'用5448区位码表示;
这里就是ASCII码表:http://cs.scu.edu.cn/~guobing/c_lan/ppt/ASCII.pdf
这里就是国标区位码表:http://www.xaipe.edu.cn/xwfb/newsfile/20061218120842.doc
Unicode码表请查看官网。
但是处理不同的标准是痛苦的,如汉语,*有一个Big5编码标准,很多编码和国标是相同的,为了解决中文问题,不能从扩展ASCII的角度入手,也不能仅靠中国一家来解决。而必须有一个全新的编码系统,这个系统要可以将中文、英文、法文、德文……等等所有的文字统一起来考虑,为每个文字都分配一个单独的编码,这样才不会有上面那种现象出现。于是,Unicode诞生了。
以上就是我们说的字符集,下面简单说下字符集编码:
Java中Unicode用两个字节表示(UCS-2),但只规定了怎么用多个字节表示各种文字,怎样传输这些编码,这就是由UTF(UCS Transformation Format)规范规定的,常见的UTF规范包括UTF-8、UTF-16等,这就是字符集编码;这里只说UTF-8:
UTF-8用1到6个字节编码UNICODE字符。如果Unicode字符由2个字节表示,则编码成UTF-8很可能需要3个字节,UFT-8转换表表示如下:
UNICODE UTF-8
0000 - 007F 0xxxxxxx
0080 - 07FF 110xxxxx 10xxxxxx
0800 - FFFF 1110xxxx 10xxxxxx 10xxxxxx
如'中'的Unicode是 4e2d,显然落在了0800 - FFFF 区,就用三个字节表示:11100100 10111000 10101101; 就是把4e2d转换成2进制0100 1110 0010 1101,依次填入XXX符号就行了。
国标码,全称是GB2312-80, 要理解国标码,楼主得先理解 区位码、国标码与机内码的关系;简单说下:
(1)区位码先转换成十六进制数表示
(2)区位码(十六进制)+2020H=国标码(十六进制);(两位两位相加)
(3)国标码(十六进制)+8080H=机内码(十六进制); (两位两位相加)
国标码是不可能在计算机内部直接采用的,与ASCII码发生冲突,如'保' 字,国标码为31H和23H,而西文字符“1”和“#”的SCII也为31H和23H,现假如内存中有两个字节为31H和23H,;这到底是一个汉字,还是两个西文字符“1”;和“#”? 于是就出现了二义性.
所以是用机内码表示的,其实就是GBK编码,该编码标准兼容GB2312;
还说下区位码的来由:
国标码汉字及符号组成一个94行94列的二维代码表中。在此方阵中,每一行称为一个"区",每一列称为一个"位"。这个方阵实际上组成一个有94个区(编号由01到94),每个区有94个位(编号由01到94)的汉字字符集。每两个字节分别用两位十进制编码,前字节的编码称为区码,后字节的编码称为位码,此即区位码,其中,高两位为区号,低两位为位号。这样区位码可以唯一地确定某一汉字或字符;反之,任何一个汉字或符号都对应一个唯一的区位码,没有重码。
由上面的关系可以知道: 机内码(十六进制) = 区位码(十六进制) + A0A0H;
如'中'的区位码是5448,表示的是'中'在54区,48位,GBK怎样编码呢?如下:
5448的十六进制是3630;
3630 + A0A0 = D6D0;
D6D0就是GBK编码了;
这里有个编码表查询 http://blog.csdn.net/boliu218/archive/2011/01/06/6119710.aspx;
说了这么多,以下不说楼主也基本明白了。
#12
还是说下:
String old = "中文的";//这里在JVM中是Unicode
String u8 = new String(old.getBytes("gbk"),"utf-8");//这里用GBK编码,注意不再是字符串或字符了,是字节,看下GBK编码11010110 11010000 d6d0 11001110 11000100 cec4 10110101 11000100 b5c4, 你解码时用UTF-8,11010110前的110XXXXX告诉解码器是要连续两个字节来解码,问题来了,UTF-8的规范是后一个字节形式是10XXXXXX,可这里是11010000,显然处理不了,这里就要看JVM的实现,我用的是IBM的JDK,他的处理是解码不了就舍弃这两个字节,后面同样处理了。所以返回一个空字符串。
String gb = new String(u8.getBytes("utf-8"),"gbk");//上面返回了个空字符串,这里就没什么编码解码了,gb就是空的。
System.out.println(u8);//无输出
System.out.println(gb);//无数出
如果new String(old.getBytes("gbk"),"utf-8");这一步解码的处理不会发字节丢失或字节替换,后面的new String(u8.getBytes("utf-8"),"gbk");是能成功转回去的,问题是前面的解码中UTF-8能表示出GBK的编码,哪怕是我们说的乱码。
String old = "中文的";//这里在JVM中是Unicode
String u8 = new String(old.getBytes("gbk"),"utf-8");//这里用GBK编码,注意不再是字符串或字符了,是字节,看下GBK编码11010110 11010000 d6d0 11001110 11000100 cec4 10110101 11000100 b5c4, 你解码时用UTF-8,11010110前的110XXXXX告诉解码器是要连续两个字节来解码,问题来了,UTF-8的规范是后一个字节形式是10XXXXXX,可这里是11010000,显然处理不了,这里就要看JVM的实现,我用的是IBM的JDK,他的处理是解码不了就舍弃这两个字节,后面同样处理了。所以返回一个空字符串。
String gb = new String(u8.getBytes("utf-8"),"gbk");//上面返回了个空字符串,这里就没什么编码解码了,gb就是空的。
System.out.println(u8);//无输出
System.out.println(gb);//无数出
如果new String(old.getBytes("gbk"),"utf-8");这一步解码的处理不会发字节丢失或字节替换,后面的new String(u8.getBytes("utf-8"),"gbk");是能成功转回去的,问题是前面的解码中UTF-8能表示出GBK的编码,哪怕是我们说的乱码。
#13
谢谢各位,特别是
magong
(行者67685C1196C4)
bao110908
()火龙果()
结帖.
magong
(行者67685C1196C4)
bao110908
()火龙果()
结帖.
#1
不行。
因为对UTF-8合法的字节数组可能对GB不合法,反之也一样。
即,UTF-8和GB不是二进制相容的。
GB和ISO-8859-1可以这样互转,它们是二进制相容的。
因为对UTF-8合法的字节数组可能对GB不合法,反之也一样。
即,UTF-8和GB不是二进制相容的。
GB和ISO-8859-1可以这样互转,它们是二进制相容的。
#2
refer to this:
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
public class Test {
public static void main(String[] args) {
String str = "测试字符转换 hello word"; //默认环境,已是UTF-8编码
try {
String strGBK = URLEncoder.encode(str, "GBK");
System.out.println(strGBK);
String strUTF8 = URLDecoder.decode(str, "UTF-8");
System.out.println(strUTF8);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
#3
And:
The results:
import java.io.UnsupportedEncodingException;
public class Test {
public static void main(String[] args) throws UnsupportedEncodingException {
String old = "测试字符转换 ";//默认环境,已是UTF-8编码
String gb = new String(old.getBytes("UTF-8"), "GBK");
System.out.println(""+gb);
String u8 = new String(gb.getBytes("GBK"), "UTF-8");
System.out.println(u8);// 没有乱码
}
}
The results:
娴嬭瘯瀛楃杞崲
测试字符转换
#4
谢高手.
utf8应该包含"中文的"这样的中文吧,虽然编码位置不同于gb。
"UTF-8和GB不是二进制相容",我理解String(old.getBytes("gbk"),"utf-8")是将gbk的二进制转换成utf8相应的二进制,不知理解错在哪
#5
public static void main(String[] args) throws Exception{
String old = "中文的";
String s1 = new String(old.getBytes("gbk"),"iso-8859-1");
String s2 = new String(s1.getBytes("iso-8859-1"),"gbk");
System.out.println(s1);
System.out.println(s2);//中文的
String str = new String(old.getBytes("gbk"),"gbk");
System.out.println(str);//中文的
}
#6
不知道你在问什么。你的代码有任何可能正确的理由值得你来发帖问错在哪里?
#7
说说我的理解吧,java的String在内存中是一直的编码为utf-8的,在你声明了String之后,它在内存中就是utf-8了,你输出至控制台时,虚拟机根据本地的环境编码等因素转化为字节流,然后把这些字节流扔给操作系统,由操作系统负责打印到控制台还是输出至文件
所以我认为lz的转化为字节码之后由转为String,这步实际只是在解码+编码之后,同一存为了utf-8,jvm的内存中的统一编码方式
下面的代码,lz看看,可能有点帮助
output:
utf8:
e4 b8 ad e6 96 87 e7 9a 84 20 61 62 63 64
gbk:
d6 d0 ce c4 b5 c4 20 61 62 63 64
中文的 abcd
中文的 abcd
在这里可以看出utf-8和gbk编码的汉字编码
所以我认为lz的转化为字节码之后由转为String,这步实际只是在解码+编码之后,同一存为了utf-8,jvm的内存中的统一编码方式
下面的代码,lz看看,可能有点帮助
String old = "中文的 abcd";
byte [] utf8Decode = old.getBytes("utf-8");
System.out.println("utf8:");
for (byte b: utf8Decode) {
System.out.print(Integer.toHexString(b & 0xFF));
System.out.print(" ");
}
System.out.println();
byte [] gbkDecode = old.getBytes("gbk");
System.out.println("gbk:");
for (byte b: gbkDecode) {
System.out.print(Integer.toHexString(b & 0xFF));
System.out.print(" ");
}
System.out.println();
System.out.println(new String(utf8Decode,"utf-8"));
System.out.println(new String(gbkDecode,"gbk"));
output:
utf8:
e4 b8 ad e6 96 87 e7 9a 84 20 61 62 63 64
gbk:
d6 d0 ce c4 b5 c4 20 61 62 63 64
中文的 abcd
中文的 abcd
在这里可以看出utf-8和gbk编码的汉字编码
#8
new String(old.getBytes("gbk"),"utf-8")是将中文字符串的GBK二进制编码 强制认作UTF-8二进制编码,尝试得到中文,当然不会如愿以偿。
#9
在这个帖子的 11 楼中我有详尽的回复,有兴趣的话可以去看看:
求一字符串x
http://topic.csdn.net/u/20080623/16/e0f44f00-eaf9-4d38-b325-a3cc443f2ec9.html
求一字符串x
http://topic.csdn.net/u/20080623/16/e0f44f00-eaf9-4d38-b325-a3cc443f2ec9.html
#10
简单给你解释下错在哪里.
#11
首先,楼主是知道的,Java中(JVM)字符串、字符 用的是Unicode, 这是Java的标准编码。像'中'用4E2D(16进制)表示。
其次,楼主也知道,世界很大,有很多的语言文字;也知道计算机只识别由0、1组成的代码;这里只说汉字和英文;
美国有个“美国信息交换标准编码”,即ASCII码,ASCII码是英文信息处理的标准编码,用些数字来代表字符,如'A'用数字65表示;
汉字信息处理也必须有一个统一的标准编码,中国是“*国家标准信息交换用汉字编码”,简称“国标”,国标表把七千余汉字、以及标点符号、外文字母等用一些数字来代表,如'中'用5448区位码表示;
这里就是ASCII码表:http://cs.scu.edu.cn/~guobing/c_lan/ppt/ASCII.pdf
这里就是国标区位码表:http://www.xaipe.edu.cn/xwfb/newsfile/20061218120842.doc
Unicode码表请查看官网。
但是处理不同的标准是痛苦的,如汉语,*有一个Big5编码标准,很多编码和国标是相同的,为了解决中文问题,不能从扩展ASCII的角度入手,也不能仅靠中国一家来解决。而必须有一个全新的编码系统,这个系统要可以将中文、英文、法文、德文……等等所有的文字统一起来考虑,为每个文字都分配一个单独的编码,这样才不会有上面那种现象出现。于是,Unicode诞生了。
以上就是我们说的字符集,下面简单说下字符集编码:
Java中Unicode用两个字节表示(UCS-2),但只规定了怎么用多个字节表示各种文字,怎样传输这些编码,这就是由UTF(UCS Transformation Format)规范规定的,常见的UTF规范包括UTF-8、UTF-16等,这就是字符集编码;这里只说UTF-8:
UTF-8用1到6个字节编码UNICODE字符。如果Unicode字符由2个字节表示,则编码成UTF-8很可能需要3个字节,UFT-8转换表表示如下:
UNICODE UTF-8
0000 - 007F 0xxxxxxx
0080 - 07FF 110xxxxx 10xxxxxx
0800 - FFFF 1110xxxx 10xxxxxx 10xxxxxx
如'中'的Unicode是 4e2d,显然落在了0800 - FFFF 区,就用三个字节表示:11100100 10111000 10101101; 就是把4e2d转换成2进制0100 1110 0010 1101,依次填入XXX符号就行了。
国标码,全称是GB2312-80, 要理解国标码,楼主得先理解 区位码、国标码与机内码的关系;简单说下:
(1)区位码先转换成十六进制数表示
(2)区位码(十六进制)+2020H=国标码(十六进制);(两位两位相加)
(3)国标码(十六进制)+8080H=机内码(十六进制); (两位两位相加)
国标码是不可能在计算机内部直接采用的,与ASCII码发生冲突,如'保' 字,国标码为31H和23H,而西文字符“1”和“#”的SCII也为31H和23H,现假如内存中有两个字节为31H和23H,;这到底是一个汉字,还是两个西文字符“1”;和“#”? 于是就出现了二义性.
所以是用机内码表示的,其实就是GBK编码,该编码标准兼容GB2312;
还说下区位码的来由:
国标码汉字及符号组成一个94行94列的二维代码表中。在此方阵中,每一行称为一个"区",每一列称为一个"位"。这个方阵实际上组成一个有94个区(编号由01到94),每个区有94个位(编号由01到94)的汉字字符集。每两个字节分别用两位十进制编码,前字节的编码称为区码,后字节的编码称为位码,此即区位码,其中,高两位为区号,低两位为位号。这样区位码可以唯一地确定某一汉字或字符;反之,任何一个汉字或符号都对应一个唯一的区位码,没有重码。
由上面的关系可以知道: 机内码(十六进制) = 区位码(十六进制) + A0A0H;
如'中'的区位码是5448,表示的是'中'在54区,48位,GBK怎样编码呢?如下:
5448的十六进制是3630;
3630 + A0A0 = D6D0;
D6D0就是GBK编码了;
这里有个编码表查询 http://blog.csdn.net/boliu218/archive/2011/01/06/6119710.aspx;
说了这么多,以下不说楼主也基本明白了。
其次,楼主也知道,世界很大,有很多的语言文字;也知道计算机只识别由0、1组成的代码;这里只说汉字和英文;
美国有个“美国信息交换标准编码”,即ASCII码,ASCII码是英文信息处理的标准编码,用些数字来代表字符,如'A'用数字65表示;
汉字信息处理也必须有一个统一的标准编码,中国是“*国家标准信息交换用汉字编码”,简称“国标”,国标表把七千余汉字、以及标点符号、外文字母等用一些数字来代表,如'中'用5448区位码表示;
这里就是ASCII码表:http://cs.scu.edu.cn/~guobing/c_lan/ppt/ASCII.pdf
这里就是国标区位码表:http://www.xaipe.edu.cn/xwfb/newsfile/20061218120842.doc
Unicode码表请查看官网。
但是处理不同的标准是痛苦的,如汉语,*有一个Big5编码标准,很多编码和国标是相同的,为了解决中文问题,不能从扩展ASCII的角度入手,也不能仅靠中国一家来解决。而必须有一个全新的编码系统,这个系统要可以将中文、英文、法文、德文……等等所有的文字统一起来考虑,为每个文字都分配一个单独的编码,这样才不会有上面那种现象出现。于是,Unicode诞生了。
以上就是我们说的字符集,下面简单说下字符集编码:
Java中Unicode用两个字节表示(UCS-2),但只规定了怎么用多个字节表示各种文字,怎样传输这些编码,这就是由UTF(UCS Transformation Format)规范规定的,常见的UTF规范包括UTF-8、UTF-16等,这就是字符集编码;这里只说UTF-8:
UTF-8用1到6个字节编码UNICODE字符。如果Unicode字符由2个字节表示,则编码成UTF-8很可能需要3个字节,UFT-8转换表表示如下:
UNICODE UTF-8
0000 - 007F 0xxxxxxx
0080 - 07FF 110xxxxx 10xxxxxx
0800 - FFFF 1110xxxx 10xxxxxx 10xxxxxx
如'中'的Unicode是 4e2d,显然落在了0800 - FFFF 区,就用三个字节表示:11100100 10111000 10101101; 就是把4e2d转换成2进制0100 1110 0010 1101,依次填入XXX符号就行了。
国标码,全称是GB2312-80, 要理解国标码,楼主得先理解 区位码、国标码与机内码的关系;简单说下:
(1)区位码先转换成十六进制数表示
(2)区位码(十六进制)+2020H=国标码(十六进制);(两位两位相加)
(3)国标码(十六进制)+8080H=机内码(十六进制); (两位两位相加)
国标码是不可能在计算机内部直接采用的,与ASCII码发生冲突,如'保' 字,国标码为31H和23H,而西文字符“1”和“#”的SCII也为31H和23H,现假如内存中有两个字节为31H和23H,;这到底是一个汉字,还是两个西文字符“1”;和“#”? 于是就出现了二义性.
所以是用机内码表示的,其实就是GBK编码,该编码标准兼容GB2312;
还说下区位码的来由:
国标码汉字及符号组成一个94行94列的二维代码表中。在此方阵中,每一行称为一个"区",每一列称为一个"位"。这个方阵实际上组成一个有94个区(编号由01到94),每个区有94个位(编号由01到94)的汉字字符集。每两个字节分别用两位十进制编码,前字节的编码称为区码,后字节的编码称为位码,此即区位码,其中,高两位为区号,低两位为位号。这样区位码可以唯一地确定某一汉字或字符;反之,任何一个汉字或符号都对应一个唯一的区位码,没有重码。
由上面的关系可以知道: 机内码(十六进制) = 区位码(十六进制) + A0A0H;
如'中'的区位码是5448,表示的是'中'在54区,48位,GBK怎样编码呢?如下:
5448的十六进制是3630;
3630 + A0A0 = D6D0;
D6D0就是GBK编码了;
这里有个编码表查询 http://blog.csdn.net/boliu218/archive/2011/01/06/6119710.aspx;
说了这么多,以下不说楼主也基本明白了。
#12
还是说下:
String old = "中文的";//这里在JVM中是Unicode
String u8 = new String(old.getBytes("gbk"),"utf-8");//这里用GBK编码,注意不再是字符串或字符了,是字节,看下GBK编码11010110 11010000 d6d0 11001110 11000100 cec4 10110101 11000100 b5c4, 你解码时用UTF-8,11010110前的110XXXXX告诉解码器是要连续两个字节来解码,问题来了,UTF-8的规范是后一个字节形式是10XXXXXX,可这里是11010000,显然处理不了,这里就要看JVM的实现,我用的是IBM的JDK,他的处理是解码不了就舍弃这两个字节,后面同样处理了。所以返回一个空字符串。
String gb = new String(u8.getBytes("utf-8"),"gbk");//上面返回了个空字符串,这里就没什么编码解码了,gb就是空的。
System.out.println(u8);//无输出
System.out.println(gb);//无数出
如果new String(old.getBytes("gbk"),"utf-8");这一步解码的处理不会发字节丢失或字节替换,后面的new String(u8.getBytes("utf-8"),"gbk");是能成功转回去的,问题是前面的解码中UTF-8能表示出GBK的编码,哪怕是我们说的乱码。
String old = "中文的";//这里在JVM中是Unicode
String u8 = new String(old.getBytes("gbk"),"utf-8");//这里用GBK编码,注意不再是字符串或字符了,是字节,看下GBK编码11010110 11010000 d6d0 11001110 11000100 cec4 10110101 11000100 b5c4, 你解码时用UTF-8,11010110前的110XXXXX告诉解码器是要连续两个字节来解码,问题来了,UTF-8的规范是后一个字节形式是10XXXXXX,可这里是11010000,显然处理不了,这里就要看JVM的实现,我用的是IBM的JDK,他的处理是解码不了就舍弃这两个字节,后面同样处理了。所以返回一个空字符串。
String gb = new String(u8.getBytes("utf-8"),"gbk");//上面返回了个空字符串,这里就没什么编码解码了,gb就是空的。
System.out.println(u8);//无输出
System.out.println(gb);//无数出
如果new String(old.getBytes("gbk"),"utf-8");这一步解码的处理不会发字节丢失或字节替换,后面的new String(u8.getBytes("utf-8"),"gbk");是能成功转回去的,问题是前面的解码中UTF-8能表示出GBK的编码,哪怕是我们说的乱码。
#13
谢谢各位,特别是
magong
(行者67685C1196C4)
bao110908
()火龙果()
结帖.
magong
(行者67685C1196C4)
bao110908
()火龙果()
结帖.