Java同样的汉字在服务器和本地的电脑上URLencode 出来的结果不一致


同样的汉字在服务器和本地的电脑上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();  
}    


输出:
%E4%B8%AD%E6%96%87%E5%AD%97%E7%AC%A6
%E6%B6%93%EF%BF%BD%EF%BF%BD%EF%BF%BD%E7%80%9B%EF%BF%BD%E7%BB%97%EF%BF%BD

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

查看默认编码:

[java] view pl
System.out.println(Charset.defaultCharset()); //查看默认编码  


问题又来了,两次输出的 GB2312 编码的不一样!一次那么长,一次却很短!

查看的实现源码吧!

  
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"));  
  }  
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
[java] view plain copy
  1. package sun.security.action;  
  2.   
  3. import java.security.PrivilegedAction;  
  4.   
  5. public class GetPropertyAction  
  6.   implements PrivilegedAction<String>  
  7. {  
  8.   private String theProp;  
  9.   private String defaultVal;  
  10.   
  11.   public GetPropertyAction(String paramString)  
  12.   {  
  13.     this.theProp = paramString;  
  14.   }  
  15.   
  16.   public GetPropertyAction(String paramString1, String paramString2)  
  17.   {  
  18.     this.theProp = paramString1;  
  19.     this.defaultVal = paramString2;  
  20.   }  
  21.   
  22.   public String run()  
  23.   {  
  24.     String str = System.getProperty(this.theProp);  
  25.     return (str == null) ? this.defaultVal : str;  
  26.   }  
  27. }  
所以正确的姿势是先判断你的默认编码是不是“UTF-8”,使用:Charset.defaultCharset();

如果不是,就将其转换为“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)


猜你喜欢

转载自blog.csdn.net/CSDNones/article/details/75009832