本文共 5643 字,大约阅读时间需要 18 分钟。
Java同样的汉字在服务器和本地的电脑上URLencode 出来的结果不一致
在CSDN问答中看到这个问题,通常这类问题都是由于字符串的编码导致的。
代码如下:
String oldStr = new String("中文字符"); //我的环境默认UTF-8 System.out.println(URLEncoder.encode(oldStr)); try { String newStr = new String(oldStr.getBytes(), "gb2312"); System.out.println(URLEncoder.encode(newStr)); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); }输出:
UTF-8的才是正确的。
URLEncoder.encode(String s) 过时了,使用下面的方法:
String oldStr = new String("中文字符"); try { System.out.println(URLEncoder.encode(oldStr, "utf-8")); System.out.println(URLEncoder.encode(oldStr, "gb2312")); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); }输出:
%E4%B8%AD%E6%96%87%E5%AD%97%E7%AC%A6%D6%D0%CE%C4%D7%D6%B7%FB
查看默认编码:
System.out.println(Charset.defaultCharset()); //查看默认编码
问题又来了,两次输出的 GB2312 编码的不一样!一次那么长,一次却很短!
查看的实现源码吧!
package java.net;import java.io.CharArrayWriter;import java.io.UnsupportedEncodingException;import java.nio.charset.Charset;import java.nio.charset.IllegalCharsetNameException;import java.nio.charset.UnsupportedCharsetException;import java.security.AccessController;import java.util.BitSet;import sun.security.action.GetPropertyAction;public class URLEncoder{ static BitSet dontNeedEncoding; static final int caseDiff = 32; static String dfltEncName = null; @Deprecated public static String encode(String paramString) { String str = null; try { str = encode(paramString, dfltEncName); } catch (UnsupportedEncodingException localUnsupportedEncodingException) { } return str; } public static String encode(String paramString1, String paramString2) throws UnsupportedEncodingException { int i = 0; StringBuffer localStringBuffer = new StringBuffer(paramString1.length()); CharArrayWriter localCharArrayWriter = new CharArrayWriter(); if (paramString2 == null) throw new NullPointerException("charsetName"); Charset localCharset; try { localCharset = Charset.forName(paramString2); } catch (IllegalCharsetNameException localIllegalCharsetNameException) { throw new UnsupportedEncodingException(paramString2); } catch (UnsupportedCharsetException localUnsupportedCharsetException) { throw new UnsupportedEncodingException(paramString2); } int j = 0; while (j < paramString1.length()) { int k = paramString1.charAt(j); if (dontNeedEncoding.get(k)) { if (k == 32) { k = 43; i = 1; } localStringBuffer.append((char)k); ++j; } else { do { localCharArrayWriter.write(k); if ((k < 55296) || (k > 56319) || (j + 1 >= paramString1.length())) continue; int l = paramString1.charAt(j + 1); if ((l < 56320) || (l > 57343)) continue; localCharArrayWriter.write(l); ++j; } while ((++j < paramString1.length()) && (!dontNeedEncoding.get(k = paramString1.charAt(j)))); localCharArrayWriter.flush(); String str = new String(localCharArrayWriter.toCharArray()); byte[] arrayOfByte = str.getBytes(localCharset); for (int i1 = 0; i1 < arrayOfByte.length; ++i1) { localStringBuffer.append('%'); char c = Character.forDigit(arrayOfByte[i1] >> 4 & 0xF, 16); if (Character.isLetter(c)) c = (char)(c - ' '); localStringBuffer.append(c); c = Character.forDigit(arrayOfByte[i1] & 0xF, 16); if (Character.isLetter(c)) c = (char)(c - ' '); localStringBuffer.append(c); } localCharArrayWriter.reset(); i = 1; } } return (i != 0) ? localStringBuffer.toString() : paramString1; } static { dontNeedEncoding = new BitSet(256); for (int i = 97; i <= 122; ++i) dontNeedEncoding.set(i); for (i = 65; i <= 90; ++i) dontNeedEncoding.set(i); for (i = 48; i <= 57; ++i) dontNeedEncoding.set(i); dontNeedEncoding.set(32); dontNeedEncoding.set(45); dontNeedEncoding.set(95); dontNeedEncoding.set(46); dontNeedEncoding.set(42); dfltEncName = (String)AccessController.doPrivileged(new GetPropertyAction("file.encoding")); }}通过查看源码我们可以明白,传入的第二个参数是输出的编码,而不是指将传入的第一个参数转换为什么类型的编码;
默认它应该是读取的容器(如:Tomcat)的默认编码;
我们可以通过执行以下代码查看:
dfltEncName = (String)AccessController.doPrivileged(new GetPropertyAction("file.encoding")); System.out.println(dfltEncName);需要在项目中添加一个类:GetPropertyAction.java
package sun.security.action;import java.security.PrivilegedAction;public class GetPropertyAction implements PrivilegedAction所以正确的姿势是先判断你的默认编码是不是“UTF-8”,使用:Charset.defaultCharset();{ private String theProp; private String defaultVal; public GetPropertyAction(String paramString) { this.theProp = paramString; } public GetPropertyAction(String paramString1, String paramString2) { this.theProp = paramString1; this.defaultVal = paramString2; } public String run() { String str = System.getProperty(this.theProp); return (str == null) ? this.defaultVal : str; }}
如果不是,就将其转换为“UTF-8”,使用:String newStr = new String(oldStr.getBytes(), "utf-8");
然后再编码:URLEncoder.encode(newStr, "utf-8");
======================文档信息===========================
版权声明:非商用自由转载-保持署名-注明出处
署名(BY) :testcs_dn(微wx笑)
文章出处:[无知人生,记录点滴](http://blog.csdn.net/testcs_dn)