Re: [問題] eclipse的結果正確,javac的結果錯誤

看板java作者 (I NEED YOU, LOVE)時間15年前 (2009/06/04 09:03), 編輯推噓5(500)
留言5則, 5人參與, 最新討論串4/5 (看更多)
※ 引述《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

06/04 09:47, , 1F
推... 但是不知道 m 了之後要放哪裡 Orz
06/04 09:47, 1F

06/04 09:57, , 2F
先 m 再說 XD
06/04 09:57, 2F

06/04 10:10, , 3F
除錯: -Dfile.encoding-UTF8
06/04 10:10, 3F
OK, 已修正 ※ 編輯: kene 來自: 140.119.164.116 (06/04 10:14)

06/04 13:41, , 4F
長知識,推
06/04 13:41, 4F

06/04 17:23, , 5F
好厲害 竟然會知道原因 = =+
06/04 17:23, 5F
文章代碼(AID): #1A9nrvKZ (java)
討論串 (同標題文章)
文章代碼(AID): #1A9nrvKZ (java)