リーダーをInputStreamに、ライターをOutputStreamに変換する方法は?


回答:


45

テキストエンコーディングの問題への対処は避けられませんが、Apache Commonsには既存の解決策があります。

必要なエンコーディングを選択するだけです。


7
参考:ReaderInputStreamコードには、バイトの読み取り方法にバグがあります(すべてのエンコーディングで機能するわけではありません)。証拠:illegalargumentexception.blogspot.com/2009/05/…未解決のバグがあります:issues.apache.org/bugzilla/show_bug.cgi?id
McDowell

1
クラスは、Apacheのcommons-ioライブラリにあります:commons.apache.org/proper/commons-io
AlikElzin-kilaka 14

@McDowell、あなたが言及したバグは、Apache Antの実装にあり、commons-ioではありません。そのため、この回答には関係ありません。
ローマ

94

文字列から始める場合は、次の操作も実行できます。

new ByteArrayInputStream(inputString.getBytes("UTF-8"))

7
優れたReaderInputStream実装では必要なメモリが少なくなります-配列内のすべてのバイトを一度に格納する必要はありません。
Piotr Findeisen 2015

3
(たとえば)標準入力で入力を受け付けるコードを単体テストする必要があるときに機能するため、このソリューションが気に入っています。
Kedar Mhaswade

42

さて、Readerは文字を扱い、InputStreamはバイトを扱います。エンコーディングは、文字をバイトとして表現する方法を指定するため、問題を無視することはできません。問題を回避することに関しては、私の意見は次のとおりです。1つの文字セット(たとえば「UTF-8」)を選択し、それを使い続けます。

実際にそれを行う方法、などが指摘されているについては、「これらのクラスのための明白な名前がありReaderInputStreamWriterOutputStream」驚くべきことに、「これらはJavaライブラリに含まれていない「反対」のクラス、にも関わらず」InputStreamReaderののOutputStreamWriterが あります含まれています。

したがって、Apache Commons IOを含む多くの人々が独自の実装を考え出しました。ライセンスの問題によっては、プロジェクトにcommons-ioライブラリを含めたり、ソースコードの一部(ここからダウンロード可能)をコピーすることもできます

ご覧のとおり、両方のクラスのドキュメントには、「JREでサポートされているすべての文字セットエンコーディングは正しく処理されている」と記載されています。

注意:他の回答の1つに対するコメントでは、このバグについて言及しています。ただし、これは、Apache Commons IO ReaderInputStreamクラスではなく、Apache Ant ReaderInputStreamクラス(ここ)に影響します。


19

また、Stringで始める場合は、次のようにCommons IOの org.apache.commons.io.IOUtilsを使用して、StringReaderの作成をスキップし、InputStreamを1つのステップで作成できます。

InputStream myInputStream = IOUtils.toInputStream(reportContents, "UTF-8");

もちろん、テキストエンコーディングについて考える必要がありますが、少なくとも変換は1つのステップで行われます。


4
このメソッドは基本的new ByteArrayInputStream(report.toString().getBytes("utf-8"))にを実行します。これには、レポートの2つの追加コピーのメモリへの割り当てが含まれます。レポートが大きければ、それは悪いことです。私の答えを見てください。
Oliv 2014

8

使用する:

new CharSequenceInputStream(html, StandardCharsets.UTF_8);

このようにする先行の変換を必要としないStringし、その後にbyte[]レポートが大きい場合には、より多くのヒープメモリを割り当て、。StringBufferからストリームが読み込まれると、その場でバイトに変換されます。

Apache Commons IOプロジェクトのCharSequenceInputStreamを使用します。



5

これらのクラスのわかりやすい名前は、ReaderInputStreamおよびWriterOutputStreamです。残念ながら、これらはJavaライブラリに含まれていません。しかし、グーグルはあなたの友達です。

悪夢のようなテキストエンコーディングの問題をすべて回避できるかどうかはわかりません。

RFEはありますが、クローズされており、修正されません。


1
bugs.openjdk.java.net/browse/JDK-4103785には、「文字セットコーディング用のパブリックAPIがあります...これらのクラスを追加する説得力のある理由はありません」というコメントが含まれています。図書館、12年後ですか?
Piotr Findeisen 2015


4

の内容をに書き込もうとしReaderていOutputStreamますか?もしそうなら、あなたは簡単に時間の折り返しを持っているだろうOutputStreamOutputStreamWriterと書き込みcharの秒ReaderWriter、代わりに読者を変換しようとしますInputStream

final Writer writer = new BufferedWriter(new OutputStreamWriter( urlConnection.getOutputStream(), "UTF-8" ) );
int charsRead;
char[] cbuf = new char[1024];
while ((charsRead = data.read(cbuf)) != -1) {
    writer.write(cbuf, 0, charsRead);
}
writer.flush();
// don't forget to close the writer in a finally {} block

1

WriterOutputStreamを使用するときの警告-バイナリデータのファイルへの書き込みを常に処理するわけではありません。通常の出力ストリームと同じです。これに問題があり、追跡するのにしばらく時間がかかりました。

可能であれば、出力ストリームをベースとして使用することをお勧めします。文字列を書き込む必要がある場合は、ストリームの周りにOUtputStreamWriterラッパーを使用してください。逆の場合よりもテキストをバイトに変換する方がはるかに信頼性が高く、これがWriterOutputStreamが標準Javaライブラリの一部ではない理由と考えられます



-1

javaが提供するものだけを使用してストリーム内の文字列を読み取るため。

InputStream s = new BufferedInputStream( new ReaderInputStream( new StringReader("a string")));

6
ReaderInputStreamはApache Commons IOにあります。
ビーソンは2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.