出力ストリームを文字列に取得する


580

出力をjava.io.OutputStreamからJavaの文字列にパイプする最良の方法は何ですか?

メソッドがあるとしましょう:

  writeToStream(Object o, OutputStream out)

これは、特定のデータをオブジェクトから指定されたストリームに書き込みます。ただし、この出力をできるだけ簡単に文字列に取得したいと考えています。

私は次のようなクラス(未テスト)を書くことを検討しています:

class StringOutputStream extends OutputStream {

  StringBuilder mBuf;

  public void write(int byte) throws IOException {
    mBuf.append((char) byte);
  }

  public String getString() {
    return mBuf.toString();
  }
}

しかし、もっと良い方法はありますか?テストを実行したいだけです。


6
ASCIIバイトしかありませんか?コードページは必要ありませんか?
Horcrux7 2008年

この場合、はい。しかし、良い点-私はそれについて考えていませんでした。
Adrian Mouat、2008年

回答:


607

私は使用しByteArrayOutputStreamます。そして最後にあなたは呼び出すことができます:

new String( baos.toByteArray(), codepage );

以上:

baos.toString( codepage );

ためのStringコンストラクタ、codepageとすることができるStringのか、インスタンスいるjava.nio.charset.Charset。可能な値はjava.nio.charset.StandardCharsets.UTF_8です。

このメソッドtoString()Stringcodepageパラメーターとしてa のみを受け入れます(スタンドJava 8)。


8
ByteArrayOutputStreamにはtoArray()メソッドはありません。ただし、toByteArray()は必要です。答えを修正できますか?また、やや簡単なbaos.toString(String charsetName)を使用しないでください。
Jonikの2009年

35
バイト配列は単なるバイナリデータです。(Unicode)テキストはさまざまな方法でバイナリにエンコードできるため、ByteArrayOutputStreamはバイトのエンコードに使用されたエンコードを知る必要があるため、同じエンコードを使用してバイトを文字列に再度デコードできます。引数なしでtoStringを使用するだけでは、問題に取り組む代わりに問題を無視するだけなので賢明ではありません。Javaはプラットフォームのエンコーディングを使用しますが、これは正しい可能性があります... 基本的にランダムです。テキストをバイトに書き込むために使用されたエンコーディングを確認し、そのエンコーディングをtoStringに渡す必要があります。
Stijn de Witt

10
ここで参照されているコードページの明確化:JavaではCharset.defaultCharset()またはCharset.forName( "specific charset");を使用できます。私のために働いたのは:new String(baos.toByteArray()、Charset.defaultCharset());
ウォレスブラウン

7
@WallaceBrownを使用することdefaultCharsetは、文字セットを完全に無視することとtoString
同じ

4
StandardCharsets.UTF_8はでCharsetはなくStringです。さらに、パラメータは呼び出されますが、呼び出されcharsetNameませんcodepage
OrangeDog

46

私はApache Commons IOライブラリが好きです。そのバージョンを見てみましょうByteArrayOutputStreamあり、toString(String enc)同様の方法をtoByteArray()。Commonsプロジェクトのような既存の信頼できるコンポーネントを使用すると、コードを小さくして拡張や再利用を容易にすることができます。


10
自分の1年を節約し、すべての一般的なAPIを読んで、問題が発生したときに、完全にテストされ、コミュニティが所有するソリューションを解き放つことができます。
Bob Herrmann

15
うーん、私は熱心なApache Commonsユーザーですが、この場合、JDK自体のjava.io.ByteArrayOutputStreamではなくCommons IOのByteArrayOutputStreamを使用する必要がある理由がわかりません。後者は、toString(String charsetName)およびtoByteArray()メソッドも提供します。詳しく説明しますか?
Jonikの2009年

1
ええ、元のコンテキストがコンテンツをストリーミングおよび抽出するためのより良い方法だったので、出力ストリームを生成するための未定義/疑問のあるメカニズムの 'write(InputStream)'メソッドが含まれていたので、Commons IOの例を含めました。私もJDKを使用します。
Joe Liversedge、

23

これはうまくいきました

OutputStream output = new OutputStream() {
    private StringBuilder string = new StringBuilder();

    @Override
    public void write(int b) throws IOException {
        this.string.append((char) b );
    }

    //Netbeans IDE automatically overrides this toString()
    public String toString() {
        return this.string.toString();
    }
};

メソッド呼び出し= >> marshaller.marshal( (Object) toWrite , (OutputStream) output);

次に、文字列を出力するか、「出力」ストリーム自体を参照するだけです。例として、文字列をコンソールに出力します= >> System.out.println(output);

参考までに:私のメソッド呼び出しmarshaller.marshal(Object,Outputstream)はXMLを操作するためのものです。このトピックとは無関係です。

これは実稼働での使用には非常に無駄が多く、変換方法が多すぎて少し緩いです。これは、カスタムOuputStreamを作成して文字列を出力することが完全に可能であることを証明するためにコーディングされたものです。しかし、Horcrux7の方法を使用すれば、2つのメソッド呼び出しだけですべてがうまくいきます。

そして、世界は別の日に住んでいます...


9
バイトをcharにキャストするだけでは、ASCIIでのみ機能します。Horcrux7のようなByteArrayOutputStreamを使用します
Dave Ray

2
デイブ・レイに同意した。バイトがASCII文字であるとは限りません。エンコーディングを使用してバイトを解釈する必要があります。byteArrayOutputStream.toString( "UTF-8")または新しいString(byteArrayOutputStream.toByteArray()、 "UTF-8")を使用します。
Martin Dow、

16

これが私がやったことです:

Obj.writeToStream(toWrite, os);
try {
    String out = new String(os.toByteArray(), "UTF-8");
    assertTrue(out.contains("testString"));
} catch (UnsupportedEncondingException e) {
    fail("Caught exception: " + e.getMessage());
}

ここで、osはByteArrayOutputStreamです。


2
@JavaJigs私はほぼ5年前に私の答えの下部でこれを明らかにしました:)
Adrian Mouat

19
で置き換えること"UTF-8"を検討してくださいStandardCharsets.UTF_8
james.garriss

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