String的getBytes()默認編碼問題


我們學習java 基礎的時候. 我們都知道在main 方法中String getBytes() 方法如果不指定編碼格式, 默認是UTF-8 的方法進行的編碼. 我們一直認為默認的編碼格式就是UTF-8. 直到我們學習了javaWeb. Servlet . 我們通過getBytes() 獲取的是按照GBK 進行編碼的. 至此我們就有了疑惑. 這個getBytes() 方法到底是怎么選擇默認編碼的. 我們帶着疑惑, 去翻一下String 的源代碼.
[AppleScript]  純文本查看 復制代碼
?
1
2
3
public byte[] getBytes ( ) {
         return StringCoding.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 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;
         }
     }
從以上源碼中可以看出是通過
[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 (
                     new GetPropertyAction ( "file.encoding" ) ) ;
                 Charset cs = lookup ( csn ) ;
                 if ( cs ! = null )
                     defaultCharset = cs;
                 else
                     defaultCharset = forName ( "UTF-8" ) ;
             }
         }
         return defaultCharset;
     }
從以上源碼中我們不難看出,不出異常的情況下.默認編碼是由file.encoding決定的.我們分別在main方法和Servlet中去獲取file.encoding去測試一下.
[AppleScript]  純文本查看 復制代碼
?
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 ) ) ;
     }
}
輸出結果是
[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 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 ) ;
     }
}
輸出結果是:
[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 -8 Demo


運行結果就是:

[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()默認編碼格式問題就解決了.

更多免費技術資料可關注:annalin1203


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM