zoukankan      html  css  js  c++  java
  • String的getBytes()默认编码问题

    我们学习java基础的时候.我们都知道在main方法中String的getBytes()方法如果不指定编码格式,默认是UTF-8的方法进行的编码.我们一直认为默认的编码格式就是UTF-8.直到我们学习了javaWeb.在Servlet中.我们通过getBytes()获取的是按照GBK进行编码的.至此我们就有了疑惑.这个getBytes()方法到底是怎么选择默认编码的.我们带着疑惑,去翻一下String的源代码.
    1 public byte[] getBytes() {
    2         return StringCoding.encode(value, 0, value.length);
    3     }
    继续跟进StringCoding的encode方法
     1 static byte[] encode(char[] ca, int off, int len) {
     2         String csn = Charset.defaultCharset().name();
     3         try {
     4             // use charset name encode() variant which provides caching.
     5             return encode(csn, ca, off, len);
     6         } catch (UnsupportedEncodingException x) {
     7             warnUnsupportedCharset(csn);
     8         }
     9         try {
    10             return encode("ISO-8859-1", ca, off, len);
    11         } catch (UnsupportedEncodingException x) {
    12             // If this code is hit during VM initialization, MessageUtils is
    13             // the only way we will be able to get any kind of error message.
    14             MessageUtils.err("ISO-8859-1 charset not available: "
    15                              + x.toString());
    16             // If we can not find ISO-8859-1 (a required encoding) then things
    17             // are seriously wrong with the installation.
    18             System.exit(1);
    19             return null;
    20         }
    21     }
    从以上源码中可以看出是通过
    1 String csn = Charset.defaultCharset().name();
    来获取默认编码方式的.
    我们继续跟进.查看Charset的defaultCharSet()方法.
     1 public static Charset defaultCharset() {
     2         if (defaultCharset == null) {
     3             synchronized (Charset.class) {
     4                 String csn = AccessController.doPrivileged(
     5                     new GetPropertyAction("file.encoding"));
     6                 Charset cs = lookup(csn);
     7                 if (cs != null)
     8                     defaultCharset = cs;
     9                 else
    10                     defaultCharset = forName("UTF-8");
    11             }
    12         }
    13         return defaultCharset;
    14     }
    从以上源码中我们不难看出,不出异常的情况下,
    默认编码是由file.encoding决定的.我们分别在main方法和Servlet中去获取file.encoding去测试一下.
    1 public class Demo {
    2     public static void main(String[] args) {
    3         System.out.println("file.encoding="+System.getProperty("file.encoding"));
    4         byte[] bytes = "黑马程序员".getBytes();
    5         System.out.println(Arrays.toString(bytes));
    6     }
    7 }
    输出结果是
    1 file.encoding=UTF-8
    2 [-23, -69, -111, -23, -87, -84, -25, -88, -117, -27, -70, -113, -27, -111, -104]
    在Servlet中的测试代码:
     1 @WebServlet("/user/findAllServlet")
     2 public class ServletDemo1 extends HttpServlet {
     3     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     4         System.out.println("findAllServlet...");
     5         System.out.println("file.encoding="+System.getProperty("file.encoding"));
     6         byte[] bytes = "黑马程序员".getBytes();
     7         System.out.println(Arrays.toString(bytes));
     8     }
     9  
    10     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    11         this.doPost(request, response);
    12     }
    13 }
    输出结果是:
    1 file.encoding=GBK
    2 [-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

    1 C:UsersyanjingpanDesktop>java Demo
    2 file.encoding=GBK
    3 [-70, -38, -62, -19, -77, -52, -48, -14, -44, -79]

    我们将Demo.java文件改成UTF-8编码格式的用 javac -encoding utf-8 Demo.java进行编译.然后运行发现file.encoding竟然没有变:

    1 C:UsersyanjingpanDesktop>java Demo
    2 file.encoding=GBK
    3 [-70, -38, -62, -19, -77, -52, -48, -14, -44, -79]

    说明file.encoding跟编译环境没有关系.只跟运行环境有关.我们尝试运行的时候指定file.encoding编码:

    1 java -Dfile.encoding=utf-8 Demo

    运行结果就是:

    1 file.encoding=utf-8
    2 [-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 C:UsersyanjingpanDesktop>java Demo
    2 file.encoding=GBK
    3 [-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()默认编码格式问题就解决了.

    我是一个小小的搬运工,让米粒变成仓廪
  • 相关阅读:
    10.19的一些题
    10.18 模拟赛
    bzoj 2212 Tree Rotations
    10.11的一些题
    10.15 模拟赛
    bzoj 5329 战略游戏
    php面向对象基础(二)
    php面向对象基础(一)
    PHP基础-数组与数据结构
    php基础-字符串处理
  • 原文地址:https://www.cnblogs.com/ricehome/p/14152296.html
Copyright © 2011-2022 走看看