作者kene (I NEED YOU, LOVE)
看板java
标题Re: [问题] eclipse的结果正确,javac的结果错误
时间Thu Jun 4 09:03:52 2009
※ 引述《Holocaust123 (Terry)》之铭言:
: ※ 引述《sbrhsieh (sbr)》之铭言:
: : 问题出在这里。
: : main.java line 57:
: : br = new BufferedReader(new InputStreamReader((InputStream)obj));
: : 这样子是以系统预设的编码(encoding)来建立 InputStreamReader,应该要使用
: : 网页 response 的 Content-Type header value 指定的 charset。
: : 比如 Yahoo 知识这一页:
: : http://tw.knowledge.yahoo.com/question/question?qid=1509051800784
: : Content-Type 是 "text/html; charset=utf-8",你就要使用 UTF-8 来 decode
: : 网页的输出(byte sequence)。
: : 你现在的程式如果在一个预设 encoding 不是 UTF-8 的 JRE 环境执行,在使用
: : BufferedReader 读取网页输出时会失真,使用 regular expression 当然也就无法
: : 正确找出你要的资讯。
: 还有个问题~
: 我做了五个实验。
: <实验一>
: 假如用原来的程式码,在 cmd 使用 kene 大的方法,也就是打:
: javac -encoding UTF8 main.java
: java -Dfile.encoding=UTF8 main
: 这样程式在执行的时候,cmd呈现出来的是乱码:
: http://www.dumpt.com/img/viewer.php?file=06z8kxokigxrk7xniqo2.jpg
: 但其实 html 的 title 不是乱码,有正确被存到 questions.txt 当中,
: 打开 questions.txt後,看到的 title 都是正确编码的 title:
: 询问医药界的业务员??跳得过去吗?(我本身是电子零件业务员)
: 急急急....这样会怀孕吗?
: 安装DirectX 9.0还是不能玩NBA2008(20)
: 基测成绩爆冲的人
: 基金获利问题~要如何判断获利
: 请问眼睛常常会有很多的分泌物,要怎麽清洁比较好?比较可以清洁
: 商标法简易判决
: 即时通怪怪的~
: ....
: (下面省略)
: 然後,我刚刚查 Java API Document,
: 发现 InputStreamReader 其实可以产生一个指定的 charset decoder 的
: InputStreamReader物件:
: http://java.sun.com/j2se/1.4.2/docs/api/java/io/InputStreamReader.html
: API里面提到:
: 「InputStreamReader(InputStream in, CharsetDecoder dec)
: Create an InputStreamReader that uses the given charset decoder.」
: 所以我就做第二个实验。
: <实验二>
: 把 main.java 的这一行
: br = new BufferedReader(new InputStreamReader((InputStream)obj));
: 改成
: br = new BufferedReader(new InputStreamReader((InputStream)obj,"UTF-8"));
: 然後在 cmd 底下打
: javac -encoding main.java
: java main
: 这样程式在 cmd 执行的时候显示出来的中文字就都不是乱码了:
: http://www.dumpt.com/img/viewer.php?file=itrmank1mrl0kalmx9a8.jpg
: 而且存入 questions.txt 的 html title 也都不是乱码。
: <实验三>
: 程式码同实验二,只是 cmd 的指令打的不一样。
: br = new BufferedReader(new InputStreamReader((InputStream)obj,"UTF-8"));
: cmd 底下打
: javac -encoding UTF8 main.java
: java -Dfile.encoding=UTF8 main
: 这样 cmd 底下看的是乱码,
: 但 questions.txt 的内文不是乱码。
: <实验四>
: 做这个实验是因为我觉得 java -Dfile.encoding main 怪怪的,
: 好像应该要打 java -Dfile.decoding main 比较合理 @@
: 程式码同实验二,cmd底下打
: javac -encoding UTF8 main.java
: java -Dfile.dncoding=UTF8 main
: 这样 cmd底下看的不是乱码,
: question.txt的内文也不是乱码。
: <实验五>
: 程式码同实验一,
: 也就是没更动 br = new BufferedReader(new InputStreamReader((InputStream)obj));
: cmd 底下打
: javac -encoding UTF8 main.java
: java -Dfile.decoding=UTF8 main
: 这样 cmd 底下本来该是 title 的部分,显示的都是一堆换行,
: questions.txt显示的的也都是一堆换行。
因为你有几个概念忽略了, 也可能是以前没想过. 以下是过去的经验,
因为没翻书验证, 所以也可能有误, 敬请板友不吝指教:
首先, 对程式 (JVM) 来说, 记忆体内存放的字串编码通通是 Unicode (好像是
UTF-16?), 但是对 I/O 来说, 编码其实是可以指定的, 不指定的话就是用系统预设值.
所以从你最初的问题来说, 你要编译 UTF-8 的 main.java 出现问题, 那是因为 javac
(这也是只 Java 程式) 在你没指定编码时, 就假设你使用的是系统预设值, 这个值在
中文 (台湾) 的地域 (Locale) 时, 会是 Big-5 / MS950. 如果预设编码不合你意,
javac 提供了 -encoding 选项, 让你可以指定编译时的编码, 所以你下
javac -encoding UTF8 main.java
时编译就一切正常. 现在开始换执行你的程式, 你的程式尝试要去 "知识家" 抓资料.
但是连线时并没有指定编码, 所以一开始执行时程式就假设你用 MS950 编码去抓资料,
自然就爆炸了 XD 但是你如果以以下的方式指定 Java I/O 的编码为 UTF8 来执行
java -Dfile.encoding=UTF8 main
那问题就消失了. 当然你也可以直接在程式里指定 I/O 编码, 如在 InputStreamReader
建构式里直接指定也行 (在此, 你的实验也已经这麽做了). 至此你的程式可以交差了
XD
再来我们将焦点转到 Windows Console (cmd.exe) 上. Windows 的 Console
其实还满阳春的, 在 中文 (台湾) 的环境下, 你几乎就只能使用 MS950 当作输出字串.
(有方法更改成 Unicode 吗? 有的话我也想知道) 如果我们直接采用前述
-Dfile.encoding 的方式强制指定使用 UTF8 时, 程式输出到 Console 上的字串也会用
UTF8 编码, 但是 Windows 上的 Console 又没聪明到会自动转换编码, 所以就再次爆炸
XD
但如果是以 InputStreamReader 指定编码的方式撰写, 那麽编码指定的范围就仅止於
InputStreamReader 所触及的部分, 对於 Console 上的输出, 还是用系统预设的编码
(MS950), 所以 JVM 就自动将记忆体内存放的 Unicode 字串转换为 Windows Console
能接受的 MS950 输出.
最後, 为啥使用 -Dfile.decoding 执行程式出来的结果不如预期? 因为 file.decoding
是无效的参数 XD 更正确地说, 这应该不能叫做参数, 而是叫做系统属性 (System
Properties) 这里
http://www.mindspring.com/~mgrand/java-system-properties.htm
有人列出了 Java 1.2 之前 JRE 内部会用到的属性 (我反而找不到 Sun 自己公告的).
很明显的只有 file.encoding 可以用, file.decoding 是不存在的. 如果指定了程式
(JVM) 读不懂的系统属性时, 程式就会当作你没指定过. 所以跑出来的结果会跟没指定
-Dfile.decoding 时效果一样.
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 140.119.164.116
1F:推 PsMonkey:推... 但是不知道 m 了之後要放哪里 Orz 06/04 09:47
2F:推 superlubu:先 m 再说 XD 06/04 09:57
3F:推 H45:除错: -Dfile.encoding-UTF8 06/04 10:10
OK, 已修正
※ 编辑: kene 来自: 140.119.164.116 (06/04 10:14)
4F:推 SmileJoS:长知识,推 06/04 13:41
5F:推 Holocaust123:好厉害 竟然会知道原因 = =+ 06/04 17:23