倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

XML 文書を読み込むのに InputStream と Reader どちらを使えばいい?

さて問題。 次のうち正しいのはどれ?

  1. XML 文書を読み込むのには InputStream よりは Reader を使う方がよい
  2. XML 文書を読み込むのには Reader よりは InputStream を使う方がよい
  3. XML 文書を読み込むのには Reader を使うべきである
  4. XML 文書を読み込むのには InputStream を使う方べきである
  5. XML 文書を読み込むのには InputStream, Reader どちらを使っても同じである
  6. それ以外

java.io パッケージには InputStreamReader というクラスがあるので、Reader を使うように統一しておけば簡単なようにも思いますが、実際には(いくつかの例外を除いて)XML 文書を読み込むのには InputStream を使う方べきであるというのが正解です。

InputStream と Reader は何が違う?


XML 文書を読み込むのには InputStream を使う方べきである」理由は、InputStream と Reader とは何が違うかというところからきています。 ではまた問題。 次のうち正しいのはどれ?

  1. InputStream より Reader の方が優れている。 InputStream は互換性や C 系言語の名残である
  2. Reader より InputStream の方が優れている。 Reader は互換性や C 系言語の名残である
  3. InputStream も Reader も大差ない
  4. InputStream と Reader には次のような違いがある:
    • InputStream は入力を byte で読み込み、それが何の文字かには関知感知しない。 文字のエンコーディングは(もし必要なら) InputStream を使用する側が指定できる
    • Reader は入力を char として読み込み、文字のエンコーディングは Reader インスタンスを作成した際に決定される。 このエンコーディングは Reader を使用する側では変更できない

ヒントは、「XML 文書は文書内にエンコーディング指定がしてあるので、読み込み側がエンコーディングを指定したい」ということです。

答えは問題文を見れば言うまでもないかな。

Reader から読み込む場合


では XML 文書の読み込みに Reader は必要ないか?と言われるとそうでもなくて、「内容が XML 文書の String オブジェクトから XML 文書を読み込む」ときには InputStream を使いようがなくて、java.io.StringReader を使って読み込みを実行します*1

ライブラリ


JAXP を見ていると org.xml.sax.InputSource (SAX) や javax.xml.stream.InputFactory (StAX) では InputStream も Reader もサポートされてますが、javax.xml.parsers.SAXParser (SAX), javax.xml.parsers.DocumentBuilder (DOM) では InputStream しかサポートされてないようです(InputSource を介せば Reader も使えますが)。

また、StAX の javax.xml.XMLStreamReader では実際のエンコーディングと XML 文書に指定されているエンコーディングを別々に取得できるように

  • getEncoding()
  • getCharacterEncodingScheme()

という2つの似たようなメソッドが定義されています。

ちなみに上記の InputStream/Reader の話は OutputStream/Writer の話にも通じますが、 Groovy の groovy.xml.MarkupBuilder では「Writer は使えるけど OutputStream は使えない」という妙な使用になってます。

Java&XML 第2版

Java&XML 第2版


入門XML

入門XML

*1:この場合はエンコーディングを指定する必要はありませんが、場合によっては(UTF-8 以外のエンコーディング指定がされていれば) XML のエンコーディング指定と読み込みのエンコーディングがずれる場合もあるかと。