首页新闻动态正文

String的getBytes()默认编码问题【黑马java培训】

更新时间:2019年07月26日 11时16分41秒 来源:黑马程序员论坛



我们学习java基础的时候.我们都知道在main方法中StringgetBytes()方法如果不指定编码格式,默认是UTF-8的方法进行的编码.我们一直认为默认的编码格式就是UTF-8.直到我们学习了javaWeb.Servlet.我们通过getBytes()获取的是按照GBK进行编码的.至此我们就有了疑惑.这个getBytes()方法到底是怎么选择默认编码的.我们带着疑惑,去翻一下String的源代码.
[AppleScript] 纯文本查看 复制代码
public byte[] getBytes() {
        return StringCoding.encode(value, 0, value.length);
    }
继续跟进StringCoding的encode方法
[AppleScript] 纯文本查看 复制代码
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] 纯文本查看 复制代码
 String csn = Charset.defaultCharset().name();
来获取默认编码方式的.我们继续跟进.查看Charset的defaultCharSet()方法.
[AppleScript] 纯文本查看 复制代码
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] 纯文本查看 复制代码
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] 纯文本查看 复制代码
file.encoding=UTF-8
[-23, -69, -111, -23, -87, -84, -25, -88, -117, -27, -70, -113, -27, -111, -104]
在Servlet中的测试代码:
[AppleScript] 纯文本查看 复制代码
@WebServlet("/user/findAllServlet")
public class ServletDemo1 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] 纯文本查看 复制代码
file.encoding=GBK
[-70, -38, -62, -19, -77, -52, -48, -14, -44, -79]
getBytes()方法的默认编码确实是跟file.encoding一致的.file.encoding是由谁决定的呢?网上很多流传说是跟当前文件的编码格式相同.那我们测试一下.
在idea中我们讲文件的编码格式改成GBK.
发现事与愿违.file.encoding依然是UTF-8的.也就是说file.encoding跟文件的编码没有任何关系.相同的代码.我们用命令行窗口去编译和运行.发现file.encoding竟然变成了GBK
[AppleScript] 纯文本查看 复制代码
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] 纯文本查看 复制代码
C:\Users\yanjingpan\Desktop>java Demo
file.encoding=GBK
[-70, -38, -62, -19, -77, -52, -48, -14, -44, -79]

这说明file.encoding跟编译环境没有关系.只跟运行环境有关.我们尝试运行的时候指定file.encoding编码:
[AppleScript] 纯文本查看 复制代码
java -Dfile.encoding=utf-8 Demo

运行结果就是:
[AppleScript] 纯文本查看 复制代码
file.encoding=utf-8
[-23, -69, -111, -23, -87, -84, -25, -88, -117, -27, -70, -113, -27, -111, -104]

运行时将file.encoding指定成gbk
[AppleScript] 纯文本查看 复制代码
java -Dfile.encoding=gbk Demo

运行结果就是:
[AppleScript] 纯文本查看 复制代码
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] 纯文本查看 复制代码
set "JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG% -Dfile.encoding=UTF-8"

重启Tomcat.再访问我们的Servlet.file.encoding就改成UTF-8的了.

至此,困扰我们的getBytes()默认编码格式问题就解决了.

推荐了解热门学科

java培训 Python人工智能 Web前端培训 PHP培训
区块链培训 影视制作培训 C++培训 产品经理培训
UI设计培训 新媒体培训 产品经理培训 Linux运维
大数据培训 智能机器人软件开发




传智播客是一家致力于培养高素质软件开发人才的科技公司“黑马程序员”是传智播客旗下高端IT教育品牌。自“黑马程序员”成立以来,教学研发团队一直致力于打造精品课程资源,不断在产、学、研3个层面创新自己的执教理念与教学方针,并集中“黑马程序员”的优势力量,针对性地出版了计算机系列教材50多册,制作教学视频数+套,发表各类技术文章数百篇。

传智播客从未停止思考

传智播客副总裁毕向东在2019IT培训行业变革大会提到,“传智播客意识到企业的用人需求已经从初级程序员升级到中高级程序员,具备多领域、多行业项目经验的人才成为企业用人的首选。”

中级程序员和初级程序员的差别在哪里?
项目经验。毕向东表示,“中级程序员和初级程序员最大的差别在于中级程序员比初级程序员多了三四年的工作经验,从而多出了更多的项目经验。“为此,传智播客研究院引进曾在知名IT企业如阿里、IBM就职的高级技术专家,集中研发面向中高级程序员的课程,用以满足企业用人需求,尽快补全IT行业所需的人才缺口。

何为中高级程序员课程?

传智播客进行了定义。中高级程序员课程,是在当前主流的初级程序员课程的基础上,增加多领域多行业的含金量项目,从技术的广度和深度上进行拓展“我们希望用5年的时间,打造上百个高含金量的项目,覆盖主流的32个行业。”传智播客课程研发总监于洋表示。




黑马程序员热门视频教程【点击播放】

Python入门教程完整版(懂中文就能学会) 零起点打开Java世界的大门
C++| 匠心之作 从0到1入门学编程 PHP|零基础入门开发者编程核心技术
Web前端入门教程_Web前端html+css+JavaScript 软件测试入门到精通


在线咨询 我要报名
和我们在线交谈!