Java 用于IOUtils.toString(InputStream)的番石榴当量

Java 用于IOUtils.toString(InputStream)的番石榴当量,java,io,inputstream,guava,Java,Io,Inputstream,Guava,有一种非常方便的方法可以将InputStream读取到字符串中 因为我正试图从Apache Commons迁移到:在番石榴中是否有一个等价物?我查看了com.google.common.io包中的所有类,但找不到任何简单的类 编辑:我理解并欣赏字符集的问题。碰巧我知道我所有的源代码都是ASCII(是的,ASCII,不是ANSI等),所以在这种情况下,编码对我来说不是问题。如果你有一个可读的,你可以使用CharStreams.toString(可读的)。因此,您可能可以执行以下操作: String

有一种非常方便的方法可以将
InputStream
读取到字符串中

因为我正试图从Apache Commons迁移到:在番石榴中是否有一个等价物?我查看了
com.google.common.io
包中的所有类,但找不到任何简单的类


编辑:我理解并欣赏字符集的问题。碰巧我知道我所有的源代码都是ASCII(是的,ASCII,不是ANSI等),所以在这种情况下,编码对我来说不是问题。

如果你有一个
可读的
,你可以使用
CharStreams.toString(可读的)
。因此,您可能可以执行以下操作:

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

强制您指定一个字符集,我想您无论如何都应该这样做。

。您可以使用以下内容:

InputSupplier<InputStreamReader> readerSupplier = CharStreams.newReaderSupplier
    (streamSupplier, Charsets.UTF_8);
String text = CharStreams.toString(readerSupplier);
ByteSource source = ...
String text = source.asCharSource(Charsets.UTF_8).read();
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));

你在对Calum回答的评论中表示你将使用

CharStreams.toString(new InputStreamReader(supplier.get(), Charsets.UTF_8))
此代码有问题,因为重载
CharStreams.toString(可读)
表示:

不关闭可读取的

这意味着您的
InputStreamReader
,以及由
supplier.get()
返回的
InputStream
,在该代码完成后将不会关闭

另一方面,如果您利用您似乎已经拥有
InputSupplier
并使用重载
CharStreams.toString(InputSupplier
),则
toString
方法将为您处理
读取器的创建和关闭

这正是Jon Skeet所建议的,只是实际上没有任何过载的
CharStreams.newReaderSupplier
InputStream
作为输入。。。您必须给它一个
输入供应商

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);
要比这更详细,请执行以下操作:

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月

在Guava 16.0中,
InputSupplier
OutputSupplier
以及使用它们的方法已被弃用。它们的替代品是
ByteSource
CharSource
ByteSink
CharSink
。给定一个
字节源
,您现在可以将其内容作为
字符串
获取,如下所示:

InputSupplier<InputStreamReader> readerSupplier = CharStreams.newReaderSupplier
    (streamSupplier, Charsets.UTF_8);
String text = CharStreams.toString(readerSupplier);
ByteSource source = ...
String text = source.asCharSource(Charsets.UTF_8).read();
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));

根据公认的答案,下面是一个实用方法,它模拟了
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);
    }
}

更新:回顾过去,我不喜欢我以前的解决方案。此外,现在是2013年,现在有更好的替代品可用于Java7。我现在用的是:

InputStream fis = ...;
String text;
try (  InputStreamReader reader = new InputStreamReader(fis, Charsets.UTF_8)){
        text = CharStreams.toString(reader);
}
或者如果与输入供应商联系

InputSupplier spl=。。。
try(InputStreamReader=spl.getInput()){
text=CharStreams.toString(读卡器);
}
编辑(2015):是我所知道的Java/Android中I/O的最佳抽象和工具。我一直在用它

这是我用的

如果我手头已经有一条流,那么:

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));
最终输入流;//这是从某处收到的
字符串s=CharStreams.toString(CharStreams.newReaderSupplier(newInputSupplier)(){
公共InputStream getInput()引发IOException{
回流;
}
},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));
String s=CharStreams.toString(CharStreams.newReaderSupplier(newInputSupplier)(){
公共InputStream getInput()引发IOException{
返回;
}
},Charsets.UTF_(8));
作为一个具体的例子,我可以阅读如下Android文本文件资产:

InputSupplier<InputStreamReader> readerSupplier = CharStreams.newReaderSupplier
    (streamSupplier, Charsets.UTF_8);
String text = CharStreams.toString(readerSupplier);
ByteSource source = ...
String text = source.asCharSource(Charsets.UTF_8).read();
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));
final Context=。。。;
字符串s=CharStreams.toString(CharStreams.newReaderSupplier(newInputSupplier)(){
公共InputStream getInput()引发IOException{
返回context.getAssets().open(“my_asset.txt”);
}
},Charsets.UTF_(8));

另一个选项是从流中读取字节并从中创建字符串:

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

它不是“纯”番石榴,但有点短。

举个具体的例子,下面是我如何读取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;
}

当输入流来自类路径资源时,有更短的自动关闭解决方案:

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

使用番石榴,灵感来自。

事实上,我将结合您和Jon Skeet的答案:`CharStreams.toString(新的InputStreamReader(supplier.get(),Charsets.UTF_8))`Yep,有很多方法可以组合选项@S.P.Floyd:如果您有一个
InputStreams供应商
,我强烈建议您使用
CharStreams.newReaderSupplier(供应商,Charsets.UTF_8)
,而不是
new InputStreamReader
。原因是当给定
InputStreamReader
时,
toString
不会关闭该
读取器(因此也不会关闭底层流!)。通过为
读卡器
使用
InputSupplier
toString
方法将为您处理关闭
读卡器的问题。关于字符集:库要求您指定您知道正在处理的字符集(例如
charsets.US\u ASCII
)而不是让您说“呃,我猜是什么字符集?”这对很多人来说似乎都很高兴。特别是因为Java没有使用像UTF-8这样有意义的默认值。我知道。这就是为什么我在自己的回答中使用UTF-8作为默认版本。另请参阅文档:@Vadzim当问这个问题时,这些文档并不存在:-)谢谢您提供的好信息(+1).但这是非常冗长的。我认为将公认的答案与Closeables相结合更简单。@CollinD:我在我的一个答案中使用了你的方法。请看一下,并告诉我这是否是使用InputSupplier的正确方法。@CollinD,如果inputStream来自doPost servlet内部,关闭它有什么意义吗?(或担心关闭它)CharStreams.toString(InputSuppli