URLEncoder和URLDecoder(乱码处理)

前言

在进行向服务器传递表单数据的实验的时候,发现得到的英文字符正常而中文字符都是乱码。在百思不得其解的时候,学习了一下URLEncoder和URLDecoder,以及顺藤摸瓜找到了产生乱码的原因和解决办法,在此记录一波。

URLEncoder和URLDecoder

URLEncoder和URLDecoder主要用完成普通字符和application/x-www-form-urlencodedMIME字符串之间的相互转换,是HTML格式编码的实用工具类。

转换规则:

  • 字母数字字符 “a” 到 “z”、“A” 到 “Z” 和 “0” 到 “9” 保持不变。
  • .特殊字符 “.”、"-"、"*" 和 “_” 保持不变。
  • 空格字符 " " 转换为一个加号 “+”。
  • 所有其他字符都是不安全的,因此首先使用一些编码机制将它们转换为一个或多个字节。然后每个字节用一个包含 3 个字符的字符串 “%xy” 表示,其中 xy 为该字节的两位十六进制表示形式。推荐的编码机制是 UTF-8。但是,出于兼容性考虑,如果未指定一种编码,则使用相应平台的默认编码。

示例代码

try {
    String url = "测试中文串";
    System.out.println(url);

    //通过utf-8编码把中文字符串转化为application/x-www-form-urlencodedMIME字符串
    String encodeUrl = URLEncoder.encode(url, "utf-8");
    System.out.println(encodeUrl);

    //同样通过utf-8编码把application/x-www-form-urlencodedMIME字符串解码为原来的字符串
    String decodeUrl = URLDecoder.decode(encodeUrl, "utf-8");
    System.out.println(decodeUrl);
} catch (Exception e) {
    e.printStackTrace();
}

结果输出

测试中文串
%E6%B5%8B%E8%AF%95%E4%B8%AD%E6%96%87%E4%B8%B2
测试中文串

乱码产生原因以及解决

乱码产生原因:服务器端在调用request.getParameter(parameterName)获取参数之前会自动通过"ISO8859-1"编码对参数进行了一次解码操作,相当于调用了一次 URLDecoder.decode(parameterValue, “ISO8859-1”)。在我们获取到参数之后,又对获取到的参数进行了一次解码,于是出现了乱码现象。相对于:

try {
	String url = "测试中文串";
	System.out.println(url);
	
	//经过编码后得到application/x-www-form-urlencodedMIM*字符串
	String encodeUrl = URLEncoder.encode(url, "utf-8");
	System.out.println(encodeUrl);
	
	//服务器端自动进行的解码操作
	encodeUrl = URLDecoder.decode(encodeUrl, "ISO8859-1"); 
	System.out.println(encodeUrl);
	
	//我们获取到参数的时候进行的操作
	String decodeUrl = URLDecoder.decode(encodeUrl, "utf-8");
	System.out.println(decodeUrl);
} catch (Exception e) {
	e.printStackTrace();
}

于是我们得到带有乱码的结果:

测试中文串
%E6%B5%8B%E8%AF%95%E4%B8%AD%E6%96%87%E4%B8%B2
???è???????????
???è???????????

针对这种现象,这里提供了两种解决方法:
方法一:利用String的构造函数进行转码(常用,推荐)

  1. 先将经过服务器解码的字符串用getBytes(“ISO8859-1”)方法,转换为"ISO8859-1"编码的字节数组
  2. 再用String的构造方法将上一步的到的字节数组按指定的字符集(如"utf-8")解码为字符串
String decodeUrl = new String(encodeUrl.getBytes("ISO8859-1"), "utf-8");

解决效果演示:

try {
	String url = "测试中文串";
	System.out.println(url);
	
	String encodeUrl = URLEncoder.encode(url, "utf-8");
	System.out.println(encodeUrl);
	
	//服务器端自动进行的解码操作
	encodeUrl = URLDecoder.decode(encodeUrl, "ISO8859-1"); 
	System.out.println(encodeUrl);
	
	//转码操作
	String decodeUrl = new String(encodeUrl.getBytes("ISO8859-1"), "utf-8");
	System.out.println(decodeUrl);
} catch (Exception e) {
	e.printStackTrace();
}

运行效果:

测试中文串
%E6%B5%8B%E8%AF%95%E4%B8%AD%E6%96%87%E4%B8%B2
???è???????????
测试中文串

方法二:开始时对中文参数进行两次”utf-8“编码
这个方法同样可以解决这个问题,由上文给出的规则可以知道,第二次编码是对第一次编码的到的串中的’%'进行编码,虽然解码的时候使用的是ISO-8859-1,但是对于%和字母数字而言用ISO-8859-1和UTF-8解码出来的是一样的,这样经过服务器的自动解码就可以得到第一次编码得到的串。当我们获取到参数再次用"utf-8"解码的时候,就可以得到原来的中文字符串了。
//此部分不作演示

参考资料

  1. https://www.cnblogs.com/caozx/p/9628576.html
  2. https://www.jianshu.com/p/3597ea96c35c
  3. https://blog.csdn.net/dreamzuora/article/details/79841295
发布了59 篇原创文章 · 获赞 103 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_42292229/article/details/97389205