web-dev-qa-db-ja.com

IOUtils.toString(InputStream)と同等のグアバ

Apache Commons IO には便利なメソッドがあります IOUtils.toString()InputStreamを文字列に読み取ります。

私はApache Commonsから Guava :に移動しようとしているので、Guavaに同等のものはありますか? com.google.common.ioパッケージのすべてのクラスを調べましたが、これほど簡単なものは見つかりませんでした。

編集:文字セットの問題を理解し、感謝しています。すべてのソースがASCII(はい、ASCII、ANSIなどではありません)など)にあることを知っているので、この場合、エンコードは問題ではありません。

104

Calumの回答に対するコメントで、使用するつもりであると述べた

_CharStreams.toString(new InputStreamReader(supplier.get(), Charsets.UTF_8))
_

オーバーロードCharStreams.toString(Readable)の状態は次のとおりです。

Readableを閉じません。

これは、あなたのInputStreamReader、および拡張によりsupplier.get()によって返されるInputStreamは、このコードの完了後に閉じられないことを意味します。

一方、すでに_InputSupplier<InputStream>_があり、オーバーロード_CharStreams.toString(InputSupplier<R extends Readable & Closeable>_)を使用しているように見えるという事実を利用する場合、toStringメソッドは作成と終了の両方を処理しますあなたのためのReaderの。

これは、入力としてInputStreamを受け取る_CharStreams.newReaderSupplier_のオーバーロードが実際にないことを除いて、Jon Skeetが提案したとおりです... InputSupplierを指定する必要があります。

_InputSupplier<? extends InputStream> supplier = ...
InputSupplier<InputStreamReader> readerSupplier = 
    CharStreams.newReaderSupplier(supplier, Charsets.UTF_8);

// InputStream and Reader are both created and closed in this single call
String text = CharStreams.toString(readerSupplier);
_

InputSupplierのポイントは、Guavaが__い_try-finally_ブロックを必要とする部分を処理できるようにして、リソースが適切に閉じられるようにすることで、生活を楽にすることです。

編集:個人的に、私は次のことを見つけました(実際にそれを書く方法は、上記のコードの手順を壊しただけです)

_String text = CharStreams.toString(
    CharStreams.newReaderSupplier(supplier, Charsets.UTF_8));
_

farこれより冗長ではない:

_String text;
InputStreamReader reader = new InputStreamReader(supplier.get(), 
    Charsets.UTF_8);
boolean threw = true;
try {
  text = CharStreams.toString(reader);
  threw = false;
}
finally {
  Closeables.close(reader, threw);
}
_

これは多かれ少なかれ、これを自分で適切に処理するために書く必要があるものです。


編集:2014年2月

InputSupplierおよびOutputSupplierおよびそれらを使用するメソッドは、Guava 16.0で非推奨になりました。それらの置換は、ByteSourceCharSourceByteSink、およびCharSinkです。 ByteSourceを指定すると、次のようにその内容をStringとして取得できます。

_ByteSource source = ...
String text = source.asCharSource(Charsets.UTF_8).read();
_
82
ColinD

Readableがある場合は、CharStreams.toString(Readable)を使用できます。したがって、おそらく次のことができます。

String string = CharStreams.toString( new InputStreamReader( inputStream, "UTF-8" ) );

文字セットを指定するように強制しますが、とにかく行うべきだと思います。

55
Calum

[〜#〜] update [〜#〜]:振り返ってみると、古いソリューションが気に入らない。それに加えて、それは現在2013年であり、Java7で利用可能なより良い代替手段があります。だからここに私が今使っているものがあります:

InputStream fis = ...;
String text;
try (  InputStreamReader reader = new InputStreamReader(fis, Charsets.UTF_8)){
        text = CharStreams.toString(reader);
}

またはInputSupplierの場合

InputSupplier<InputStreamReader> spl = ...
try (  InputStreamReader reader = spl.getInput()){
        text = CharStreams.toString(reader);
    }
15
husayt

ほぼ。次のようなものを使用できます。

_InputSupplier<InputStreamReader> readerSupplier = CharStreams.newReaderSupplier
    (streamSupplier, Charsets.UTF_8);
String text = CharStreams.toString(readerSupplier);
_

個人的に私はdo n'tIOUtils.toString(InputStream)が「いい」と思う-それは常にプラットフォームのデフォルトのエンコーディングを使用するからで、それはあなたが望むものとはほとんど決して違う。エンコーディングの名前を取得するオーバーロードがありますが、名前を使用することは素晴らしいアイデアではありません。だから_Charsets.*_が好きです。

編集:上記がstreamSupplierとして_InputSupplier<InputStream>_を必要とするわけではありません。既にストリームを取得している場合は、十分に簡単に実装できます。

_InputSupplier<InputStream> supplier = new InputSupplier<InputStream>() {
    @Override public InputStream getInput() {
        return stream;
    }
};
_
15
Jon Skeet

別のオプションは、Streamからバイトを読み取り、それらから文字列を作成することです。

new String(ByteStreams.toByteArray(inputStream))
new String(ByteStreams.toByteArray(inputStream), Charsets.UTF_8)

「純粋な」グアバではありませんが、少し短くなっています。

11
ponomandr

受け入れられた答えに基づいて、IOUtils.toString()(および文字セットを含むオーバーロードバージョン)の動作を模倣するユーティリティメソッドを次に示します。このバージョンは安全なはずですよね?

public static String toString(final InputStream is) throws IOException{
    return toString(is, Charsets.UTF_8);
}


public static String toString(final InputStream is, final Charset cs)
throws IOException{
    Closeable closeMe = is;
    try{
        final InputStreamReader isr = new InputStreamReader(is, cs);
        closeMe = isr;
        return CharStreams.toString(isr);
    } finally{
        Closeables.closeQuietly(closeMe);
    }
}
4

入力ストリームがクラスパスリソースから来る場合、より短い自動クローズソリューションがあります。

URL resource = classLoader.getResource(path);
byte[] bytes = Resources.toByteArray(resource);
String text = Resources.toString(resource, StandardCharsets.UTF_8);

IOExplained に触発されたGuava Resources を使用します。

3
Vadzim

[〜#〜] edit [〜#〜](2015): Okio は、I/O私が知っているJava/Androidで。いつも使っています。

FWIWは私が使用するものです。

既に手元にストリームがある場合は、次のようにします。

final InputStream stream; // this is received from somewhere
String s = CharStreams.toString(CharStreams.newReaderSupplier(new InputSupplier<InputStream>() {
    public InputStream getInput() throws IOException {
        return stream;
    }
}, Charsets.UTF_8));

ストリームを作成している場合:

String s = CharStreams.toString(CharStreams.newReaderSupplier(new InputSupplier<InputStream>() {
    public InputStream getInput() throws IOException {
        return <expression creating the stream>;
    }
}, Charsets.UTF_8));

具体的な例として、Androidテキストファイルアセットを次のように読むことができます。

final Context context = ...;
String s = CharStreams.toString(CharStreams.newReaderSupplier(new InputSupplier<InputStream>() {
    public InputStream getInput() throws IOException {
        return context.getAssets().open("my_asset.txt");
    }
}, Charsets.UTF_8));
2
orip

具体的な例として、Androidテキストファイルアセットを読み取る方法は次のとおりです。

public static String getAssetContent(Context context, String file) {
    InputStreamReader reader = null;
    InputStream stream = null;
    String output = "";

    try {
        stream = context.getAssets().open(file);
        reader = new InputStreamReader(stream, Charsets.UTF_8);
        output = CharStreams.toString(reader);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (stream != null) {
            try {
                stream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if (reader != null) {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    return output;
}
0
TruMan1