String的getBytes()預設編碼問題
阿新 • • 發佈:2020-12-18
我們學習java基礎的時候.我們都知道在main方法中String的getBytes()方法如果不指定編碼格式,預設是UTF-8的方法進行的編碼.我們一直認為預設的編碼格式就是UTF-8.直到我們學習了javaWeb.在Servlet中.我們通過getBytes()獲取的是按照GBK進行編碼的.至此我們就有了疑惑.這個getBytes()方法到底是怎麼選擇預設編碼的.我們帶著疑惑,去翻一下String的原始碼.
[AppleScript]純文字檢視複製程式碼
繼續跟進StringCoding的encode方法
[AppleScript]純文字檢視複製程式碼
從以上原始碼中可以看出是通過
[AppleScript]純文字檢視複製程式碼
來獲取預設編碼方式的.我們繼續跟進.檢視Charset的defaultCharSet()方法.
[AppleScript]純文字檢視複製程式碼
從以上原始碼中我們不難看出,不出異常的情況下.預設編碼是由file.encoding決定的.我們分別在main方法和Servlet中去獲取file.encoding去測試一下.
[AppleScript]純文字檢視複製程式碼
輸出結果是
[AppleScript]純文字檢視複製程式碼
在Servlet中的測試程式碼:
[AppleScript]純文字檢視複製程式碼
輸出結果是:
[AppleScript]純文字檢視複製程式碼
getBytes()方法的預設編碼確實是跟file.encoding一致的.file.encoding是由誰決定的呢?網上很多流傳說是跟當前檔案的編碼格式相同.那我們測試一下.
在idea中我們講檔案的編碼格式改成GBK.
<ignore_js_op>
1 2 3 |
public byte[] getBytes ( ) {
return StringCoding.encode ( value , 0 , value .length ) ;
}
|
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 name encode ( ) variant which provides caching.
return encode ( csn , ca , off , len ) ;
} catch ( UnsupportedEncodingException x ) {
warnUnsupportedCharset ( csn ) ;
}
try {
return encode ( "ISO-8859-1" , ca , off , len ) ;
} catch ( UnsupportedEncodingException x ) {
/ / If this code is hit during VM initialization , MessageUtils is
/ / the only way we will be able to get any kind of error message .
MessageUtils.err ( "ISO-8859-1 charset not available: "
+ x.toString ( ) ) ;
/ / If we can not find ISO -8859 -1 ( a required encoding ) then things
/ / are seriously wrong with the installation.
System.exit ( 1 ) ;
return null;
}
}
|
1 |
String csn = Charset.defaultCharset ( ) . name ( ) ;
|
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 (
new GetPropertyAction ( "file.encoding" ) ) ;
Charset cs = lookup ( csn ) ;
if ( cs ! = null )
defaultCharset = cs;
else
defaultCharset = forName ( "UTF-8" ) ;
}
}
return defaultCharset;
}
|
1 2 3 4 5 6 7 |
public class Demo {
public static void main ( String[] args ) {
System.out.println ( "file.encoding=" + System.getProperty ( "file.encoding" ) ) ;
byte[] bytes = "黑馬程式設計師" .getBytes ( ) ;
System.out.println ( Arrays.toString ( bytes ) ) ;
}
}
|
1 2 |
file .encoding = UTF -8
[ -23 , -69 , -111 , -23 , -87 , -84 , -25 , -88 , -117 , -27 , -70 , -113 , -27 , -111 , -104 ]
|
01 02 03 04 05 06 07 08 09 10 11 12 13 |
@WebServlet ( "/user/findAllServlet" )
public class ServletDemo 1 extends 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 ) ;
}
}
|
1 2 |
file .encoding = GBK
[ -70 , -38 , -62 , -19 , -77 , -52 , -48 , -14 , -44 , -79 ]
|
發現事與願違.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竟然沒有變:
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編碼:
1 |
java - Dfile.encoding = utf -8 Demo
|
執行結果就是:
1 2 |
file .encoding = utf -8
[ -23 , -69 , -111 , -23 , -87 , -84 , -25 , -88 , -117 , -27 , -70 , -113 , -27 , -111 , -104 ]
|
執行時將file.encoding指定成gbk
1 |
java - Dfile.encoding = gbk Demo
|
執行結果就是:
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.
1 |
set "JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG% -Dfile.encoding=UTF-8"
|
重啟Tomcat.再訪問我們的Servlet.file.encoding就改成UTF-8的了.
<ignore_js_op>
至此,困擾我們的getBytes()預設編碼格式問題就解決了.