以为很简单的问题耗时一天,尚未有完美解决方案。。
解决方案以及分析参阅:
http://www.360doc.com/content/13/0830/14/1073512_310953718.shtml
关键字:Java中文字符编码乱码详述
http://javarevisited.blogspot.com/2012/01/get-set-default-character-encoding.html
关键字: How to get and set default Character encoding or Charset in Java
详情待我慢慢道来。。。
项目需求: 解析java文件,从中获取package, class, method, testng的annotation等。
本来这个东西用ruby已经实现了,而且工作良好,但是因为平台的问题,非要重新用java实现。。。擦
自然而然找到了javaParser,用起来还是很顺手。
但是项目要求打包成可执行的jar文件,这就苦了我了。
把我们另外一个项目的拿过来做测试包,使用eclipse运行,完美无误。
但是打包之后通过命令行运行就是各种错误。
基本上就是遇到了中文,以色列语(希伯来语)的时候出的错误。
之前对java编码这块也不是很熟(常年用ruby, python解决这类字符串问题),真的不知道水能有tm这么深!
首先尝试读入和写入的编码。
先讲下IO流的转换过程。
从github上下载项目压缩包 -> 读入zipinputstream -> 然后将符合条件的文件(至少得是java吧,至少里面得有@Test吧)转换成inputstream传给JavaParser,然后由其解析。
错误就出在inputstream传给javaParser这块。
一开始一直以为是我转换到inputstream时的问题,然后使用utf-8从zipinputstream切到inputstream,然后将inputstream给javapaser, 同时给javaparser一个utf-8的参数让它按照这个编码读。。。
经过2个多小时的折腾,发现我擦,完全没用。
其间遇到状况是这样的: 使用utf-8吧,一部分文件解析失败。不使用吧,这些没问题了,另外一些突然又有问题了。。。
其间还遇到了utf-8还是utf8还是UTF-8的问题。。。
经过又1个多小时的折腾,发现还是没思路,然后找来大牛(因为很壮,跟牛很像)帮忙。
大牛的思路(等下你会看到也挺奇葩的,哈哈):
对,是编码的问题,那么我们看看这些文件都是什么类型的编码呢,我们按照类型进行读入不就行了?(这里完全正确!但是后面就给带偏了。。)
发现大部分文件是没有编码格式的,然后少部分是使用utf-8保存的。
思路就是如果没有格式的,我们使用最广泛能兼容的格式,用到了iosxxxx-15的一个格式,有格式的使用默认格式,当然就是utf-8了。
这下问题少了很多,但是还是有文件不能正确解析。
我们的要求是必须要全部兼容,因为涉及到很多个项目,不可能因为你的问题改人家项目的代码。哭。
解析来就到了好玩的地方了:我们把这些中文,希伯来语都删掉吧!
嗯?!好主意啊(我也是脑子进水了)。于是我们找到了
text.replaceAll("[^\\x00-\\x7F]", "")
这个可以替换掉所有非acsii码(待确定是不是这个意思,有熟知大叔请帮忙评论下,多谢多谢!)。
不错不错,这下子又解决了不少有问题的文件。
然后大牛要回家陪老婆过周末blabla就走掉了。。。
然后我继续继续努力吧(继续进水中。。)
慢慢发现这以后出的问题就不是解析语言的问题,而是突然发现经常会丢掉双引号。
比如正常的 String a = "bbb";就变成了 String a = "bbb;
这个就没办法了。。
等等,我想到一个好主意,正则表达式!(回想起来,惭愧的要撞墙自杀)
我试着将出现这类问题的line通过正则表达式判断出来,然后通过替换将双引号加上。
(说道这里发现一道不错的面试题:使用java如何判断在一个字符串里,特定单词的数量。 答案见最后)
然后
然后发现了这样的:
String s1 = "private String receipt = \"特典が適用され、PayPalの領収書に表示されます;"; #分号前少一个双引
接着发现了这样的:
String s2 = "ppBtnPage.setAttributeValue(\"billing_first_name\", \"劉);"; #括号前少一个双引
我心想这就差不多了吧,这正则写的也够复杂了,我擦,理论上不应该这么玩啊。
终于当我看到还有这样的,我就崩溃了,严格意义上是脑子的水被清空了
String s3 = "@Test (testName=\"19947,groups={\"RQA_HK\", \"RQA_zh\", \"RQA_APAC\" },description=\"HSS SPARTA FLOW\")"; #TMD字符串中间少一个双引
终于明白为什么叫悟空了,脑子空了才能悟出东西来。
因为一直纠结为什么在eclipse下就能正常运行的问题,于是搜索了一下如何像eclipse一样强制按照UTF-8编码读取文件。
万万没想到,最后XX还是XXX了(好像就是这么说的吧,每集必备的台词)
万万没想到,最后问题还是被我解决了。
在可执行jar包前加上-Dfile.encoding=UTF-8之后,终于把所有文件全部解析成功。
长吁了一口气,发个短信告慰了下陪老婆的大牛这个问题我解决了,哇咔咔咔。
然后被大牛加了个需求(他是这活的主要负责人,我来帮忙的干活),把这个参数写到项目里,免得别人每次用还要重复输入。
好嘞!
心想赶紧干完这票,保存下今天的战果上传,然后发个周报给大boss,然后回家给加班的老婆做饭等老婆回家,一起吃饭看爸爸去哪儿。。。。
然后又经过了1个小时。。。
我擦,这尼玛不管用啊。
理论上(自认为是这样的,没有科学依据,大家手下留情)设置一个全局的file.encoding不就行了?
System.setProperty("file.encoding","UTF-8");
然后设置,发现运行还是出错,没道理啊。
然后这时候大牛来了,我说有个问题。。
大牛说你今天的问题权已经用完了,下周吧,呵呵呵呵。。。
我勒个去,心说我自己弄。。。哼哼哼哼
大牛过来了。
大牛说:你把这个加上不就行了(就我加的那个。。。)
然后我把功能的部分注释掉,只留了编码打印的代码给他看。
我说不行啊,你看加了这行之后,执行jar包,打印编码,还是默认的GBK。
等等。。
怎么可以了?变成UTF-8了。。。(是因为之前我使用eclipse运行的时候没有设置这个参数,直接从系统获取然后打印的,由于eclipse已经设置了默认是utf-8,所以在eclipse中自然就是UTF-8。但是jar包执行的时候还是系统默认的GBK. 当时我演示的时候把这个参数加上了,当然就起作用了)
好吧。待我把功能代码恢复下,然后看结果如何。。。
嗯???!!!改成utf-8了还是不工作啊,不工作。。
然后我又把-Dfile.encoding=UTF-8加上之后,又完美的工作了,工作了,了。。。
大牛看了看,2秒之后说,回家吧,我媳妇楼下等我呢。闪之。。。
暗暗鄙视之。。。。
然后收拾东西准备回家。。。
想到下周还要解决这个问题,然后搜索了下,获得了如上的参阅链接,晚点自己研究下。
然后写下了这篇曲折又有趣的debug经历。
你看到这篇文章发表的时间就是我下班的时间。
嗯,一天的时间+3个小时都没有搞定的问题。
嗯。。还在等老婆中,因为她已经下班回家在路上了。。。
在办公室。TT
参考关于file.encoding=UTF-8的资料
http://yang3wei.github.io/blog/2013/02/10/java-dfile-dot-encoding-equals-utf-8-gan-diao-luan-ma/
最后公布答案
问题: 使用java如何判断在一个字符串里,特定单词的数量
答案:使用split
因为java的split是支持正则的(不清楚哪个版本有的这个特性),所以我们可以讲我们需要查找的单词使用正则来进行匹配,兼容大小写的哦:)
split之后判断数组长度,将长度减1就是答案了
想到这个是因为我要判断这一行里引号的数量是不是偶数对。