たまにはJavaの勉強。
javaで標準入力の文字列をXMLとして解釈するプログラム書いた時のメモ。
環境はMac 10.6.8, java version "1.6.0_37"
ハマったポイント
- コンパイル通らないし文字化けする
- XMLのパースで例外
Javaって、XMLを解析するモジュールあるから楽勝だよねーと思って
こんな感じのを最初に書いた。
import java.util.*; import java.lang.*; import java.io.*; class Main{ public static void main (String[] args) throws Exception{ BufferedReader r = new BufferedReader (new InputStreamReader (System.in)); String s; String xmlStr = ""; while ((s=r.readLine()) != null) { xmlStr = xmlStr + s; if (s.equals("</root>")) { break; } } DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docbuilder = dbfactory.newDocumentBuilder(); byte[] byteStr = xmlStr.getBytes(); Document doc = docbuilder.parse(new ByteArrayInputStream(byteStr)); } }
よーし、レッツコンパイrうわー玉砕。
javac sample.java sample.java:18: ?V???{???????????܂???B ?V???{??: ?N???X DocumentBuilderFactory ?ꏊ : Main ?? ?N???X DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance(); ^ sample.java:18: ?V???{???????????܂???B ?V???{??: ?ϐ? DocumentBuilderFactory ?ꏊ : Main ?? ?N???X DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance(); ^ sample.java:19: ?V???{???????????܂???B ?V???{??: ?N???X DocumentBuilder ?ꏊ : Main ?? ?N???X DocumentBuilder docbuilder = dbfactory.newDocumentBuilder(); ^ sample.java:21: ?V???{???????????܂???B ?V???{??: ?N???X Document ?ꏊ : Main ?? ?N???X Document doc = docbuilder.parse(new ByteArrayInputStream(byteStr)); ^ ?G???[ 4 ??
macのターミナルはUTF-8、Javaは内部がSJISなので文字化けするそうな。
そこで、文字コードはUTF-8を使うように指定してコンパイルした。
そしたら、とてもわかりやすい結果になった!
javac -J-Dfile.encoding=utf-8 sample.java sample.java:18: シンボルを見つけられません。 シンボル: クラス DocumentBuilderFactory 場所 : Main の クラス DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance(); ^ sample.java:18: シンボルを見つけられません。 シンボル: 変数 DocumentBuilderFactory 場所 : Main の クラス DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance(); ^ sample.java:19: シンボルを見つけられません。 シンボル: クラス DocumentBuilder 場所 : Main の クラス DocumentBuilder docbuilder = dbfactory.newDocumentBuilder(); ^ sample.java:21: シンボルを見つけられません。 シンボル: クラス Document 場所 : Main の クラス Document doc = docbuilder.parse(new ByteArrayInputStream(byteStr)); ^ エラー 4 個
シンボルがないらしいので、パッケージのインポートを見直す。
見なおした↓
import java.util.*; import java.lang.*; import java.io.*; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Document; class Main{ public static void main (String[] args) throws Exception{ BufferedReader r = new BufferedReader (new InputStreamReader (System.in)); String s; String xmlStr = ""; while ((s=r.readLine()) != null) { xmlStr = xmlStr + s; if (s.equals("</root>")) { break; } } DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docbuilder = dbfactory.newDocumentBuilder(); byte[] byteStr = xmlStr.getBytes(); Document doc = docbuilder.parse(new ByteArrayInputStream(byteStr)); } }
レッツ実行。
標準入力に↓のXMLをコピペしてうわー例外発生。
java Main <?xml version="1.0" encoding="utf-8"?> <root> <item id="1"> <name>冷蔵庫</name> </item> <item id="2"> <name>テレビ</name> </item> <item id="3"> <name>掃除機</name> </item> </root> [Fatal Error] :1:116: The element type "name" must be terminated by the matching end-tag "</name>". Exception in thread "main" org.xml.sax.SAXParseException: The element type "name" must be terminated by the matching end-tag "</name>". at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:246) at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:284) at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:124) at Main.main(test_6.java:52)
XMLの解析で失敗してるくさい。
name要素はend-tagがあるべきなのにマッチングしない、おかしいって言ってるみたい。
なので、
ためしに、ソースコードにXMLを直書きしてやったら例外発生しなかった。
ためしに、日本語をAAAとかに書き換えて実行したら例外発生しなかった。
(文字コードがあやしい・・・)
コンパイル同様、Javaを実行するときに文字コード指定して実行してみた。
java -Dfile.encoding=utf-8 Main
例外発生しない!
やったーミッションコンプリート!