public static String change(String str)
{
try
{
if(str != null)
str = new String(str.getBytes("GB2312"), "ISO-8859-1");
}
catch(Exception e)
{
e.printStackTrace();
}
return str;
}
这个里面的str.getBytes("GB2312")和"ISO-8859-1"是把什么转换成什么
{
try
{
if(str != null)
str = new String(str.getBytes("GB2312"), "ISO-8859-1");
}
catch(Exception e)
{
e.printStackTrace();
}
return str;
}
这个里面的str.getBytes("GB2312")和"ISO-8859-1"是把什么转换成什么
str.getBytes("GB2312"), 的“GB2312”可以随便写吗?
--------------------------------------------------------------------------
在java中的编码大家一直可能有个误区,对编码概念的理解也一直比较模糊,那java他是怎样的一个编码
规则呢,其实如果深入的研究很容易的知道其编码过程。外部的文本或有编码的信息进入java要被java理解和处理的话,必须转变成utf-16,不管输入的是gbk
还是其它的国家的编码信息要想被java认识和处理(除非不作处理,直接当作一个黑盒子传递)就必须
得把gbk或其它国家的编码方式转换成utf-16的编码,才能被java查找和显示(System.out.println(str))
等。 当java中要输出信息时也要还原或者指定编码,告诉java请把你的utf-16转成我要的utf-8的型式。
就像字节转成字符串一样。new String(byte[] b,String charsetName)就是表示把指定的
charsetName编码转成utf-16(java系统使用的中间编码)
因为如:一个字符串为gbk格式,后来被当作utf-8读取当然会乱码,我们可以先把乱码的字符先
utf-8的方式把utf-16的字符转成字节,然后再以gbk的方式转成utf-16
有一点我们要注意,在这些转换过程中我们都是从其它编码转成utf-16,或从utf-16转成其它编码
因此utf-16是java使用的中间编码方式。16。在字符串转字节时,编码是怎样的?默认编码是怎样的。
-------------------------------------------------------------------------------------------------
测试代码如下:
String str = "ab12,n中";
byte[] bt;
try {
bt = str.getBytes("gb2312");
System.out.println(bt.length);
for(int i=0;i<bt.length;i++)
{
Byte b = (Byte)bt[i];
System.out.println(b.longValue());
}
} catch (UnsupportedEncodingException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
}
String str = "ab12,n中";
byte[] bt= str.getBytes();
System.out.println(bt.length);
for(int i=0;i<bt.length;i++)
{
Byte b = (Byte)bt[i];
System.out.println(b.longValue());
}
输出结果都为:
8
97
98
49
50
44
110
-42
-48
注:在测试中我们看gb2312的中字编码为:D6 D0
D6 = 214 256-42=214
如此说明,这里的字符默认编码使用系统的编码,也就当前系统的编码方式。我用的是简体操作系统
当然是简体编码
------------------------------------------------------------
测时,我在客户用gb2312进行提交,服务器接收时显示是乱码。TestForm fo = (TestForm) form;
String myName = fo.getMyName();//request.getParameter("myName");
System.out.println(myName);
myName = Pcode.toCode(myName,"8859_1","gb2312");
if(myName!=null)
{
System.out.println(myName);
byte[] b = myName.getBytes();
for(int i=0;i<b.length;i++)
{
System.out.println(b[i]);
}
}
return mapping.findForward("show");
从客户接收的myName如果为中文的化,显示为乱码,如果经过。
myName = Pcode.toCode(myName,"8859_1","gb2312");转换后正常了,
从而可见myName的确接收的是错误编码后在字符串,我们得用Pcode先转回去
再转回来。
这里说明几个问题。
1)默认的情况下(这里测试环境为tomcat6.0)服务器接收时的使用编码为8859_1
除非我们指定request的编码,同时编码必须和客户一致。
2)我们看到打印出来?号,如果直接输出降byte的话为63,也就是说乱码的字输出
来为?号或乱码,这是在客户转过来就乱了,还是System.out.println时乱的呢。
其实是System.out.println时乱的,println对于大于ASCII的值,但又不能显示为
中文的字显示为?号。因此并非没有转给过来,而是打印信息时出现问题。
而myName.getBytes();中的默认编码为当前系统的编码,也就是说,在把字符串
转在byte时,是把utf-16转成了gbk的字节。
测试:
-----------------------------------------------------------------------------------------------------------------
public static void main(String[] args) {
String str = "中国";
try {
byte[] b = str.getBytes("GBK"); //UTF16->GBK
print(b);
str = new String(b,"8859_1"); //8859_1->UTF16
System.out.println("----"+str);
byte[] bb = str.getBytes("GBK"); //UTF16->GBK
print(bb);
str = new String(bb,"GBK"); //GBK->UTF16
System.out.println("----"+str.length());
byte[] bc = str.getBytes("8859_1"); //UTF16->8859_1
print(bc);
str = new String(bc,"GBK"); //GBK->UTF16
System.out.println("----"+str.length());
System.out.println(str);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public static void print(byte[] b)
{
for(int i=0;i<b.length;i++)
{
System.out.println(b[i]);
}
System.out.println("------------------------");
}
输出结果:
----------------------------------------------------------------------------------------------------------------------
-42
-48
-71
-6
------------------------ //第一次输出时正常。对应于byte[] b = str.getBytes("GBK");
----???ú //在转换时出现问题,str = new String(b,"8859_1"); 前三个字节数字过大,超出ascii的表示范围,只有最后一个-6被表示为ú
63
63
63
-88
-78
------------------------
----4
63
63
63
-6
------------------------
----4
????
注:那这里真正的乱码(也就是不可还原)到底是那一个环节呢,在测试中发现,把
1)byte[] b = str.getBytes("GBK");
2)str = new String(b,"8859_1");
3)byte[] bb = str.getBytes("GBK");
这里问题出现在第三行代码,测试中发现第二行代执行后还是可以还原的。
因此测试的结果很显然是再转成GBK出现错误。其实字符串也是char[]数组,而char对于java来说,
就是用两个数字表示的,也就是utf-16.
从上面我们可以得出,中国两个字的编码为:d6d0 b9fa
在经过str = new String(b,"8859_1"); 后应为:d600 d000 b900 fa00
因为8859_1会把一个字节当一个ascii进行处理,所以表示为UTF-16时用了8个字节。也就是说相当于
表示了4个字。(UTF-16用两个字节表示一个字),如果按原来的编码还原的话,当然不会有问题。
只是重新把d600变成一个字节不行了。d6,但如果我们用GBK来进行转换的话,因为gbk也是用两个
字节来表示的,因此在转成字节后应为00d6 00d0 00b9 00fa,理论上字节数组会增长,从原来的4
变成8,但是为什么不是这样呢。很显然是byte[] bb = str.getBytes("GBK");的原因
这条语句如果碰到不是GBK字符的字就会用?号代替。
00fa确实为字符ú ,不过在字库中查找00d6也是有字符的,不知为什么是问号。