初窥java乱码问题

故事起源于这周踩的一个小坑,tomcat本地调启动web时报错。错误提示说有个xml文件的编码有问题,我点进去看了看没看出啥异常,开头跟其他xml一样指定了utf-8的格式,除了是小写的,我傻乎乎地去改成了大写。。。然后。。。肯定是没解决啊!!!咳咳,果断请教同事去了,瞅一眼,扔过来一串参数-Dfile.encoding=UTF-8,让我在webserver的VM OPTION里面加上,成了。

恩,又是那个古老的梗,(咦,好了!但是这是为什么呢。。。)虽然从头到尾我都不懂,但是还是筛选掉一些例如-D是什么鬼之类的问题吧。O(∩_∩)O。。。问题的挖掘经历了几个阶段:

1.file.encoding的系统默认值是什么(其实我也不知道有没有系统默认值这么个东西。。总之就是默认值了啊。。。哈哈。。。)

首先自然想知道默认的encoding值是什么了。我新建了一个空的工程,随便写了个类,在main里面打印System.getproperty("file.encoding")了。结果让我莫名其妙,明明就是UTF-8啊。那系统默认的输出编码格式应该就是UTF-8,应该不会出问题啊。默认的encoding为何没有用到?

2.file.encoding在哪些环节会用到

找到一篇很好地文章http://cmsblogs.com/?p=1475。文章很系统地分析了java输出格式的流程。在不同情况下的流程也是不同的。文章举例了三种情况:1)直接输出到console 2)部署到webserver输出到web页面 3)输出到数据库。这篇文章解决了我的第一个问题,也就是为什么输出到web没有用到那个UTF-8。因为System.getproperty()中得到的file.encoding代表的是输出到console时编码格式,自然跟web页面没关系。

此外我还知道了,java虚拟机在处理数据时,数据在内存中存储的格式均为Unicode,包括.class文件以及外部输入的数据。这样我可以理解成,数据在内存中一律是以Unicode格式流转的,需要输出到哪个地方就再获取对应的file.encoding,将Unicode格式的数据再转换成file.encoding的格式输出。仔细一想,其实这种方式也非常符合java的平台无关特性,毕竟有Unicode这种大杀器(能涵盖所有字符的编码格式我也是醉了),那自然要用它来作为统一的数据处理格式,至于那些关乎平台关乎场景的case,再各自分情况处理。

3.所谓的默认file.encoding值是从哪得到的

说实话这是让我非常头疼的问题,因为臣妾实在是对工具神马的一窍不通啊!!鬼知道TMD写在哪个配置文件的哪个角落里啊!!尼玛,我继续搜,不停地搜。好不容易找到了。。由IDE控制的针对console的file.encoding默认设置。我用的是intellij,在$ItellijHOME/Contents/Info.plist,(这个HOME是我瞎BB的,看得懂就好了啊。。),确实找到了这么一串

<key>VMOptions</key>
<string>-Dfile.encoding=UTF-8 -XX:+UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB=50 -ea -Dsun.io.useCanonCaches=false -Djava.net.preferIPv4Stack=true -Xverify:none -Xbootclasspath/a:../lib/boot.jar</string>

<key>WorkingDirectory</key>

看到那个“-Dfile.encoding=UTF-8”木有!!成就感满满有木有!!!故事告一段落,最开始找到的那个UTF-8来自于IDE的默认设置,并且管的是console,web容器的file.encoding在tomcat运行设置的VM OPTION重新指定为UTF-8,于是输出的web页面格式OK了。

但是!怎么可以就此止步!不是有getProperty嘛,那也有setProperty啊,你不是说输出到哪就获取对应的file.encoding然后转换unicode到file.encoding再输出么,那我先按utf-8输出,再setProperty成别的编码格式,再输出相同内容是不是就乱码了?

事实证明,企图用setproperty来修改runtime的file.encoding根本不起作用,该输出啥还是输出啥。于是我查了一下资料,file.encoding的值在JVM初始化的时候指定的才是有效地,运行时file.encoding压根就是一个只读属性,据说是初始化的时候存了一个cache,以后即使改了也只会读取cache也就是初始化的值,有兴趣的可以去读一下源码,相关的讨论链接在这了http://stackoverflow.com/questions/1749064/how-to-find-the-default-charset-encoding-in-java。自己也照着试了一下,的确如此,我只有修改vm option才会输出乱码。关键的几句代码:

new OutputStreamWriter(new ByteArrayOutputStream()).getEncoding();//查看有效的file.encoding,也就是初始化时候的那个cache值

System.getProperty("file.encoding");//查看file.encoding的真实值,虽然真实,但是无效啊。。

以上。

时间: 2024-09-30 10:04:33

初窥java乱码问题的相关文章

Java发送邮件初窥

一.背景 最近朋友的公司有用到这个功能,之前对这一块也不是很熟悉,就和他一起解决出现的异常的同时,也初窥一下使用Apache Common Email组件进行邮件发送. 二.Java发送邮件的注意事项 1.不同的邮箱有不同的支持协议,比如有些只支持SSL协议,有些只支持TLS协议,还有些同时支持SSL和TLS协议. 2.支持不同协议的邮箱,在使用Java发送邮件时要使用不同的方式发送,下面我会介绍基于SSL和TLS的两种实现方式. 附:常用邮箱的服务器(Smtp/POP3)地址和端口总结 三.代

初窥ElasticSearch

初窥ElasticSearch 官网上面的,不知道讲的是什么.. youtube上面有一个start with,内容是在windows下面跑这个elastic search,然后用一个fidler工具可视化测试 https://www.youtube.com/watch?v=60UsHHsKyN4 粗略看起来,其实es和其他db没什么大区别,只是在搜索上有很多强大功能,所以很适合用在需要搜索的项目.貌似用curl发送一个JSON格式的数据(实际上是命令)到es就可以做CRUD elasticse

玩转oo对象模型(1) 之 初窥c++对象模型

============================================== copyright: KIRA-lzn ============================================== 转载请注明出处,这篇是我原创,翻版必究! ============================================== 第二篇,如果写的好,请点个赞呦.当然有不对之处,非常欢迎拍砖!!!! 自我介绍: USTC研一学生,目前在intel实习,研发岗 第二篇

Hadoop学习笔记(9) ——源码初窥

Hadoop学习笔记(9) ——源码初窥 之前我们把Hadoop算是入了门,下载的源码,写了HelloWorld,简要分析了其编程要点,然后也编了个较复杂的示例.接下来其实就有两条路可走了,一条是继续深入研究其编程及部署等,让其功能使用的淋漓尽致.二是停下来,先看看其源码,研究下如何实现的.在这里我就选择第二条路. 研究源码,那我们就来先看一下整个目录里有点啥: 这个是刚下完代码后,目录列表中的内容. 目录/文件 说明 bin 下面存放着可执行的sh命名,所有操作都在这里 conf 配置文件所在

初窥AspectJ

AspectJ可以说是Java中当之无愧的黑魔法.说它是黑魔法,一方面是因为它很强大,能够解决一些传统编程方法论解决不了的问题,而另一方面,它也相当的晦涩,有着比较陡峭的学习曲线. 本文将带大家探索下AspectJ是什么,能做什么,以及如何来做,希望通过本文能够让大家初窥AspectJ之门道 AOP是什么 相信很多人第一次听说AOP是在学习spring的时候,笔者也是.这个概念其实困扰了我很久,到底是AOP?AOP是Aspect Oriented Programming的缩写,和OOP(Obje

Scrapy 1.4 文档 01 初窥 Scrapy

初窥 Scrapy Scrapy 是用于抓取网站并提取结构化数据的应用程序框架,其应用非常广泛,如数据挖掘,信息处理或历史存档. 尽管 Scrapy 最初设计用于网络数据采集(web scraping),但它也可用于使用 API(如 Amazon Associates Web Services)提取数据或用作通用的网络爬虫. 爬虫(spider)示例 为了向您展示 Scrapy 带给您的是什么,我们将使用最简单的方式运行一个爬虫,向您展示一个 Scrape Spider 的例子. 这是一个爬虫的

jQuery源码学习(2):选择器初窥

选择器初窥 代码架构: jQuery选择器可以依照传入数据的类型分为五大类: 传入字符串:$("div"), $("#id"), $(".div1"),$(".div p.title") 传入html代码:$("<div></div>"), $("<div>1</div><div>2</div>") 传入对象:$(d

Boost.ASIO简要分析-1 初窥

Boost.Asio是一个主要用于网络及底层I/O编程的跨平台C++库. 1. 初窥 Boost.Asio支持对I/O对象进行同步及异步操作. 1.1 同步操作 同步操作的事件顺序如下图所示: 1) 调用者调用I/O对象的connect函数开始连接操作,socket.connect(server_endpoint): 2) I/O对象将连接请求传递给io_service: 3) io_service调用操作系统函数: 4) 操作系统返回结果给io_service: 5) io_service将结

Swift初窥----深入Swift

存储函数 内存中的Fibonacci函数,避免重复递归,来提高代码执行效率 模板 编译器 Swift编译器,使其可以编译出更快的机器代码 Swift初窥----深入Swift,布布扣,bubuko.com