Javaを用いていると、提供されているAPIの関係で○○Readerから○○InputStreamに変換しないといけない場合があります。ここでは、ReaderをInputStreamに変換するための簡単な指針をメモしておきます。
(1)InputStreamクラスを継承するサブクラスを作成します。(アダプタパターン)
(2)InputStream#read()メソッド内でCharBuffer.allocate(int)を用いて、適度な大きさのCharBufferインスタンスを生成します。
(3)変換するReaderから文字列を取得し、CharBuffer#put(String)メソッドによってバッファに文字列を格納します。
(4)Charset.forName(String)によってCharsetインスタンスを生成し、さらにCharset#newEncoder()メソッドでCharsetEncoderを生成します。
(5)CharsetEncoder#encode(CharBuffer)メソッドでByteBufferに変換します。
(6)ByteBuffer#get()でbyteを取得し、InputStream#read()メソッドの返り値として返します。バッファの含まれる残りのbyte数を知りたいときは、ByteBuffer#remainig()メソッドを用います。
Comments [5]
ぜんさん
> Javaを用いていると、○○Readerから○○InputStreamに変換しないといけない場合があります。
○○Readerは、○○InputStreamが使いにくいから簡単に使えるようにできたのではないでしょうか?
わざわざ○○InputStreamに変換するのは、何か良くない方向に向かっているような気がしてなりません…。
tetsuさん
確かに普通のプログラムでは使わないですよね^^;
もともとしたかったのは、SGML(XMLの前身)ファイルを
XML形式に変換して、さらにDOMで読ませたかったんです。
でも、DOMのDocumentBuilder#parseにはFileクラスが
InputStreamクラスのインスタンスしか引数に与えられないんで
どうしようかなって思ってたところなんです。
単純な解決方法は、SGML→XMLに変換したところで
一時ファイルに落とすことなんですが、それってパフォーマンス的に
どうなのかなって思ったので思いついたアイデアでした。
でも、よく考えたらこの場合でも、Reader→InputStreamじゃなくて
Writer(もしくはOutputStream)→InputStreamなんで、
Reader→InputStreamって流れは出てこないですよね…。
エントリ書いてて思いました。
ぜんさん
確かに、そういう需要はありますね…。
私はSAXParserとXMLDecoderしか使ったことがないのですが、どちらもInputStreamしか読めません。
自分が作ったXMLを解釈させるには…私なら、Socketを使ってlocalhostと通信させちゃいますね(笑)パフォーマンス的にはダメダメですが。
tetsuさん
いい感じの方法を友達に教えてもらいました。
こういうときのために、InputSourceというクラスがあるらしく
これを使うとDocumentBuilder#parse(InputSource)で
解析できるということでした。
そんなわけで、たぶんまともな方法は
→ルート要素を付加するReaderを作成
→InputSourceでラッピング
→DocumentBuilder#parseに食わせる
ってことになるんですかね?。
tetsuさん
さらにこんなのもあるみたいです。
koders Code Search : SGMLParser.java
コメントする