itochin2の日記(仮)

主に備忘録。Perl、MySQL、Unity、開発管理などについて情報を残していきたい。

たまには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-8Javaは内部が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

例外発生しない!
やったーミッションコンプリート!