GBK UTF-8 decode 和 encode 互转

时间:2021-10-05 11:04:01
最近被编码搞头大了。

问题如下:
提交的中文如下
<input type=hidden name="MerPriv"    value="这里不填中文返回有问题">
页面使用get方式提交,GBK编码方式。
IE转码后为:  
MerPriv=%D5%E2%C0%EF%B2%BB%CC%EE%D6%D0%CE%C4%B7%B5%BB%D8%D3%D0%CE%CA%CC%E2

而我们系统偏偏是utf-8方式的。
所以系统tomcat接收后会 自动使用URLDecoder.decode(MerPriv,"UTF-8");这样处理了。

那我在java中怎么都转不回原字符了。
请教这要怎么处理。我们系统的编码方式UTF-8不能改变

16 个解决方案

#1


全部统一用UTF-8。
页面用GBK,后台用UTF-8,不是自己给自己埋炸弹么?

#2


server.conf里面能够设置

<Connector connectionTimeout="40000" port="8080" protocol="HTTP/1.1" 
        URIEncoding="UTF-8" redirectPort="8443"/>

#3


URLEncoder.encode("xxxx", "GBK");

#4


另外,推荐1楼方法,解决乱码问题的根本就是统一字符集

#5


而我们系统偏偏是utf-8方式的。是什么意思 
是说你的项目规定tomcat的encodeURI是utf-8不能改?
如果可以改就把这里改成gbk,对于get请求就ok了,
对post则更简单,用过滤器设置一下请求的编码和页面一致就ok了

对于get乱码还可以先在页面用js去encode中文,服务端再decode

#6


过程:页面GBK---> url的ISO-8859-1 ---->java的UTF-8,你在后台先将字符串转化为GBK,显示的字符串打印出来,应该是页面传过来的,比如传过来是“图书”, 如果你要是和数据库中的“图书”做查询,你就可以直接用,也就是后台把GBK的编码“图书”当做UTF-8的“图书”, 之前我做jfreechart的时候jfreechart自动产生的热点链接传参有点类似这种情况,你仔细考虑下

#7


不能统一是因为,我要接受外部系统提交的表单。
外部系统采用gbk编码,而我们系统采用utf-8编码的。

#8


引用 7 楼 zhangdream321 的回复:
不能统一是因为,我要接受外部系统提交的表单。
 外部系统采用gbk编码,而我们系统采用utf-8编码的。

晕。。。
加个filter,里面把系统得url拿到,如果是外部调用就不要decode?
不知道能不能实现。。。
头大。。

#9


引用 8 楼 crazylaa 的回复:
引用 7 楼 zhangdream321 的回复:
不能统一是因为,我要接受外部系统提交的表单。
外部系统采用gbk编码,而我们系统采用utf-8编码的。

晕。。。
加个filter,里面把系统得url拿到,如果是外部调用就不要decode?
不知道能不能实现。。。
头大。。


filter只能过滤post的提交的。
而get提交是在tomcat的server.xml  URIEncoding="UTF-8"中设置的

#10


引用 9 楼 zhangdream321 的回复:
引用 8 楼 crazylaa 的回复:
 引用 7 楼 zhangdream321 的回复:
 不能统一是因为,我要接受外部系统提交的表单。
 外部系统采用gbk编码,而我们系统采用utf-8编码的。

 晕。。。
 加个filter,里面把系统得url拿到,如果是外部调用就不要decode?
 不知道能不能实现。。。
 头大。。


 filter只能过滤post的提交的。
 而get提交是在tomcat的server.xml  URIEncoding="UTF-8"中设置的

这样说来,应该是
GBK变%C之类再变UTF-8
那先decode(**,UTF-8)
再decode(上面得,GBK)
行不行啊?

#11


crazylaa  的方法我试过,decode(**,UTF-8) 之后出现的不是 =%D5%E2%C0%EF%B2%BB%CC%EE%D6%D0%CE%C4%B7%B5%BB%D8%D3%D0%CE%CA%CC%E2 

这个东西,二是更加古怪的%E 之类的字符

#12


引用 11 楼 zhangdream321 的回复:
crazylaa  的方法我试过,decode(**,UTF-8) 之后出现的不是 =%D5%E2%C0%EF%B2%BB%CC%EE%D6%D0%CE%C4%B7%B5%BB%D8%D3%D0%CE%CA%CC%E2

 这个东西,二是更加古怪的%E 之类的字符
GBK UTF-8 decode 和 encode 互转

#13


引用楼主 zhangdream321 的回复:
而我们系统偏偏是utf-8方式的。
所以系统tomcat接收后会自动使用URLDecoder.decode(MerPriv,"UTF-8");这样处理了。

第一点,楼主的意思是否如2楼eastoneking所说,在server.xml的Connector标签中设置了URIEncoding的值为UTF-8。
引用 7 楼 zhangdream321 的回复:
不能统一是因为,我要接受外部系统提交的表单。
外部系统采用gbk编码,而我们系统采用utf-8编码的。

第二点,楼主在7楼的答复中是否是说,外部系统使用GET方式、GBK编码这一点不能改变。

================================
在这里需要注意的一点是:对于楼主维护的服务器而言,服务器接收到的表单数据在编码与提交方式上是否统一?
如果所有来自于不同服务器的网页在向你的服务器提交表单时遵守统一的规则,那么在你的服务器上统一处理就行了。
如果规则不能统一,就不能使用同一个servlet来接收不同的表单。

例如楼主提到的例子:
1. 存在GET方式提交的GBK编码的表单数据;
2. 存在GET方式提交的UTF-8编码的表单数据。

就这两点而言,首先服务器不能使用自动解码方式对GET方式提交的数据进行处理,也就是说不能在server.xml的Connector标签中指定URIEncoding的值。
其次服务器必须为上述两种表单提交提供不同的servlet;在处理GBK编码数据的servlet中使用下面的方式对数据进行解码:
String merPriv = request.getParameter("MerPriv");
merPriv = new String(merPriv.getBytes(Charset.forName("ISO-8859-1")), Charset.forName("GBK"));

在处理UTF-8编码数据的servlet中使用下面的方式对数据进行解码:
String merPriv = request.getParameter("MerPriv");
merPriv = new String(merPriv.getBytes(Charset.forName("ISO-8859-1")), Charset.forName("UTF-8"));

#14


由于中文是填写的,所以要先用js 去encode,得到%D5%E2%C0%EF%B2%BB%CC%EE%D6%D0%CE%C4%B7%B5%BB%D8%D3%D0%CE%CA%CC%E2的字符串提交到servlet,servlet用utf-8去decode就行了

#15


String merPriv = request.getParameter("MerPriv"); 
merPriv = new String(merPriv.getBytes(Charset.forName("ISO-8859-1")), Charset.forName("UTF-8")); 

这是13楼的代码有道理,但小心楼主可能没弄清是什么编码转成什么编码,所以无法按13楼的搞定
多试试吧,我猜猜可能可以这样:
转两次:
String merPriv = request.getParameter("MerPriv"); 
merPriv = new String(merPriv.getBytes("UTF-8"), "ISO-8859-1"); 
merPriv = new String(merPriv.getBytes("ISO-8859-1"), "GBK"); 
我这样猜的原因是楼主说:
所以系统tomcat接收后会自动使用URLDecoder.decode(MerPriv,"UTF-8");这样处理了。

也可能这样可以解决:
String merPriv = request.getParameter("MerPriv"); 
merPriv = new String(merPriv.getBytes("ISO-8859-1"), "UTF-8"); 
merPriv = new String(merPriv.getBytes("UTF-8"), "GBK"); 

但是前提是你的页面也是GBK编码方式,如果页面是UTF-8就不能用了。
我知道上面的做法效率较低,我的意思是你先用这个方法,如果做出来了,再做优化喽。

#16


统一用utf-8啊。。。     java程序里再加个过滤器     

#1


全部统一用UTF-8。
页面用GBK,后台用UTF-8,不是自己给自己埋炸弹么?

#2


server.conf里面能够设置

<Connector connectionTimeout="40000" port="8080" protocol="HTTP/1.1" 
        URIEncoding="UTF-8" redirectPort="8443"/>

#3


URLEncoder.encode("xxxx", "GBK");

#4


另外,推荐1楼方法,解决乱码问题的根本就是统一字符集

#5


而我们系统偏偏是utf-8方式的。是什么意思 
是说你的项目规定tomcat的encodeURI是utf-8不能改?
如果可以改就把这里改成gbk,对于get请求就ok了,
对post则更简单,用过滤器设置一下请求的编码和页面一致就ok了

对于get乱码还可以先在页面用js去encode中文,服务端再decode

#6


过程:页面GBK---> url的ISO-8859-1 ---->java的UTF-8,你在后台先将字符串转化为GBK,显示的字符串打印出来,应该是页面传过来的,比如传过来是“图书”, 如果你要是和数据库中的“图书”做查询,你就可以直接用,也就是后台把GBK的编码“图书”当做UTF-8的“图书”, 之前我做jfreechart的时候jfreechart自动产生的热点链接传参有点类似这种情况,你仔细考虑下

#7


不能统一是因为,我要接受外部系统提交的表单。
外部系统采用gbk编码,而我们系统采用utf-8编码的。

#8


引用 7 楼 zhangdream321 的回复:
不能统一是因为,我要接受外部系统提交的表单。
 外部系统采用gbk编码,而我们系统采用utf-8编码的。

晕。。。
加个filter,里面把系统得url拿到,如果是外部调用就不要decode?
不知道能不能实现。。。
头大。。

#9


引用 8 楼 crazylaa 的回复:
引用 7 楼 zhangdream321 的回复:
不能统一是因为,我要接受外部系统提交的表单。
外部系统采用gbk编码,而我们系统采用utf-8编码的。

晕。。。
加个filter,里面把系统得url拿到,如果是外部调用就不要decode?
不知道能不能实现。。。
头大。。


filter只能过滤post的提交的。
而get提交是在tomcat的server.xml  URIEncoding="UTF-8"中设置的

#10


引用 9 楼 zhangdream321 的回复:
引用 8 楼 crazylaa 的回复:
 引用 7 楼 zhangdream321 的回复:
 不能统一是因为,我要接受外部系统提交的表单。
 外部系统采用gbk编码,而我们系统采用utf-8编码的。

 晕。。。
 加个filter,里面把系统得url拿到,如果是外部调用就不要decode?
 不知道能不能实现。。。
 头大。。


 filter只能过滤post的提交的。
 而get提交是在tomcat的server.xml  URIEncoding="UTF-8"中设置的

这样说来,应该是
GBK变%C之类再变UTF-8
那先decode(**,UTF-8)
再decode(上面得,GBK)
行不行啊?

#11


crazylaa  的方法我试过,decode(**,UTF-8) 之后出现的不是 =%D5%E2%C0%EF%B2%BB%CC%EE%D6%D0%CE%C4%B7%B5%BB%D8%D3%D0%CE%CA%CC%E2 

这个东西,二是更加古怪的%E 之类的字符

#12


引用 11 楼 zhangdream321 的回复:
crazylaa  的方法我试过,decode(**,UTF-8) 之后出现的不是 =%D5%E2%C0%EF%B2%BB%CC%EE%D6%D0%CE%C4%B7%B5%BB%D8%D3%D0%CE%CA%CC%E2

 这个东西,二是更加古怪的%E 之类的字符
GBK UTF-8 decode 和 encode 互转

#13


引用楼主 zhangdream321 的回复:
而我们系统偏偏是utf-8方式的。
所以系统tomcat接收后会自动使用URLDecoder.decode(MerPriv,"UTF-8");这样处理了。

第一点,楼主的意思是否如2楼eastoneking所说,在server.xml的Connector标签中设置了URIEncoding的值为UTF-8。
引用 7 楼 zhangdream321 的回复:
不能统一是因为,我要接受外部系统提交的表单。
外部系统采用gbk编码,而我们系统采用utf-8编码的。

第二点,楼主在7楼的答复中是否是说,外部系统使用GET方式、GBK编码这一点不能改变。

================================
在这里需要注意的一点是:对于楼主维护的服务器而言,服务器接收到的表单数据在编码与提交方式上是否统一?
如果所有来自于不同服务器的网页在向你的服务器提交表单时遵守统一的规则,那么在你的服务器上统一处理就行了。
如果规则不能统一,就不能使用同一个servlet来接收不同的表单。

例如楼主提到的例子:
1. 存在GET方式提交的GBK编码的表单数据;
2. 存在GET方式提交的UTF-8编码的表单数据。

就这两点而言,首先服务器不能使用自动解码方式对GET方式提交的数据进行处理,也就是说不能在server.xml的Connector标签中指定URIEncoding的值。
其次服务器必须为上述两种表单提交提供不同的servlet;在处理GBK编码数据的servlet中使用下面的方式对数据进行解码:
String merPriv = request.getParameter("MerPriv");
merPriv = new String(merPriv.getBytes(Charset.forName("ISO-8859-1")), Charset.forName("GBK"));

在处理UTF-8编码数据的servlet中使用下面的方式对数据进行解码:
String merPriv = request.getParameter("MerPriv");
merPriv = new String(merPriv.getBytes(Charset.forName("ISO-8859-1")), Charset.forName("UTF-8"));

#14


由于中文是填写的,所以要先用js 去encode,得到%D5%E2%C0%EF%B2%BB%CC%EE%D6%D0%CE%C4%B7%B5%BB%D8%D3%D0%CE%CA%CC%E2的字符串提交到servlet,servlet用utf-8去decode就行了

#15


String merPriv = request.getParameter("MerPriv"); 
merPriv = new String(merPriv.getBytes(Charset.forName("ISO-8859-1")), Charset.forName("UTF-8")); 

这是13楼的代码有道理,但小心楼主可能没弄清是什么编码转成什么编码,所以无法按13楼的搞定
多试试吧,我猜猜可能可以这样:
转两次:
String merPriv = request.getParameter("MerPriv"); 
merPriv = new String(merPriv.getBytes("UTF-8"), "ISO-8859-1"); 
merPriv = new String(merPriv.getBytes("ISO-8859-1"), "GBK"); 
我这样猜的原因是楼主说:
所以系统tomcat接收后会自动使用URLDecoder.decode(MerPriv,"UTF-8");这样处理了。

也可能这样可以解决:
String merPriv = request.getParameter("MerPriv"); 
merPriv = new String(merPriv.getBytes("ISO-8859-1"), "UTF-8"); 
merPriv = new String(merPriv.getBytes("UTF-8"), "GBK"); 

但是前提是你的页面也是GBK编码方式,如果页面是UTF-8就不能用了。
我知道上面的做法效率较低,我的意思是你先用这个方法,如果做出来了,再做优化喽。

#16


统一用utf-8啊。。。     java程序里再加个过滤器