1. 程式人生 > 實用技巧 >String的getBytes()預設編碼問題

String的getBytes()預設編碼問題

我們學習java基礎的時候.我們都知道在main方法中String的getBytes()方法如果不指定編碼格式,預設是UTF-8的方法進行的編碼.我們一直認為預設的編碼格式就是UTF-8.直到我們學習了javaWeb.在Servlet中.我們通過getBytes()獲取的是按照GBK進行編碼的.至此我們就有了疑惑.這個getBytes()方法到底是怎麼選擇預設編碼的.我們帶著疑惑,去翻一下String的原始碼. [AppleScript]純文字檢視複製程式碼
1 2 3 public byte[] getBytes(){ returnStringCoding.encode(value,0,value.length); }
繼續跟進StringCoding的encode方法 [AppleScript]純文字檢視複製程式碼
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 static byte[] encode(char[] ca,int off,int len){ String csn =Charset.defaultCharset
().name(); try{ //use charset nameencode()variant which provides caching. returnencode(csn,ca,off,len); }catch (UnsupportedEncodingException x){ warnUnsupportedCharset(csn); } try{ returnencode("ISO-8859-1",ca,off,len); }catch (UnsupportedEncodingException x){ //If this code ishit during VM initialization
,MessageUtils is //theonly way we will be able togetany kind oferrormessage. MessageUtils.err("ISO-8859-1 charset not available: " +x.toString()); //If we can notfind ISO-8859-1(a required encoding)thenthings //are seriously wrong withtheinstallation. System.exit(1); returnnull; } }
從以上原始碼中可以看出是通過 [AppleScript]純文字檢視複製程式碼
1 String csn =Charset.defaultCharset().name();
來獲取預設編碼方式的.我們繼續跟進.檢視Charset的defaultCharSet()方法. [AppleScript]純文字檢視複製程式碼
01 02 03 04 05 06 07 08 09 10 11 12 13 14 public static Charset defaultCharset(){ if(defaultCharset ==null){ synchronized (Charset.class){ String csn =AccessController.doPrivileged( newGetPropertyAction("file.encoding")); Charset cs =lookup(csn); if(cs !=null) defaultCharset =cs; else defaultCharset =forName("UTF-8"); } } returndefaultCharset; }
從以上原始碼中我們不難看出,不出異常的情況下.預設編碼是由file.encoding決定的.我們分別在main方法和Servlet中去獲取file.encoding去測試一下. [AppleScript]純文字檢視複製程式碼
1 2 3 4 5 6 7 public classDemo { public static void main(String[] args){ System.out.println("file.encoding="+System.getProperty("file.encoding")); byte[] bytes ="黑馬程式設計師".getBytes(); System.out.println(Arrays.toString(bytes)); } }
輸出結果是 [AppleScript]純文字檢視複製程式碼
1 2 file.encoding=UTF-8 [-23,-69,-111,-23,-87,-84,-25,-88,-117,-27,-70,-113,-27,-111,-104]
在Servlet中的測試程式碼: [AppleScript]純文字檢視複製程式碼
01 02 03 04 05 06 07 08 09 10 11 12 13 @WebServlet("/user/findAllServlet") public classServletDemo1extends HttpServlet { protected void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException { System.out.println("findAllServlet..."); System.out.println("file.encoding="+System.getProperty("file.encoding")); byte[] bytes ="黑馬程式設計師".getBytes(); System.out.println(Arrays.toString(bytes)); } protected void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException { this.doPost(request,response); } }
輸出結果是: [AppleScript]純文字檢視複製程式碼
1 2 file.encoding=GBK [-70,-38,-62,-19,-77,-52,-48,-14,-44,-79]
getBytes()方法的預設編碼確實是跟file.encoding一致的.file.encoding是由誰決定的呢?網上很多流傳說是跟當前檔案的編碼格式相同.那我們測試一下. 在idea中我們講檔案的編碼格式改成GBK. <ignore_js_op>

發現事與願違.file.encoding依然是UTF-8的.也就是說file.encoding跟檔案的編碼沒有任何關係.相同的程式碼.我們用命令列視窗去編譯和執行.發現file.encoding竟然變成了GBK

[AppleScript]純文字檢視複製程式碼
1 2 3 C:\Users\yanjingpan\Desktop>java Demo file.encoding=GBK [-70,-38,-62,-19,-77,-52,-48,-14,-44,-79]


我們講Demo.java檔案改成UTF-8編碼格式的用 javac -encoding utf-8 Demo.java進行編譯.然後執行發現file.encoding竟然沒有變:

[AppleScript]純文字檢視複製程式碼
1 2 3 C:\Users\yanjingpan\Desktop>java Demo file.encoding=GBK [-70,-38,-62,-19,-77,-52,-48,-14,-44,-79]


這說明file.encoding跟編譯環境沒有關係.只跟執行環境有關.我們嘗試執行的時候指定file.encoding編碼:

[AppleScript]純文字檢視複製程式碼
1 java -Dfile.encoding=utf-8Demo


執行結果就是:

[AppleScript]純文字檢視複製程式碼
1 2 file.encoding=utf-8 [-23,-69,-111,-23,-87,-84,-25,-88,-117,-27,-70,-113,-27,-111,-104]


執行時將file.encoding指定成gbk

[AppleScript]純文字檢視複製程式碼
1 java -Dfile.encoding=gbk Demo


執行結果就是:

[AppleScript]純文字檢視複製程式碼
1 2 3 C:\Users\yanjingpan\Desktop>java Demo file.encoding=GBK [-70,-38,-62,-19,-77,-52,-48,-14,-44,-79]


到此我們就知道了.Tomcat在啟動的時候將file.encoding指定成了gbk.所以我們在Servlet中獲取位元組碼陣列的時候,預設用的就是gbk.
Tomcat是根據當前作業系統來設定file.encoding的值.我電腦是windows簡體中問的.所以預設就是GBK的.
我們可以在catalina.bat中將file.encoding設定成utf-8.

[AppleScript]純文字檢視複製程式碼
1 set"JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG% -Dfile.encoding=UTF-8"


重啟Tomcat.再訪問我們的Servlet.file.encoding就改成UTF-8的了.
<ignore_js_op>
至此,困擾我們的getBytes()預設編碼格式問題就解決了.