1. 程式人生 > >Java同樣的漢字在伺服器和本地的電腦上URLencode 出來的結果不一致

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)