Apache Commons IO有一个很好的便捷方法IOUtils.toString()来读取InputStream
到字符串。
因为我试图从Apache Commons转移到Guava:在番石榴中是否有相同的东西?我查看了com.google.common.io
包中的所有类,我找不到任何简单的东西。
编辑:我了解并了解charsets的问题。只是碰巧我知道我的所有源都是ASCII(是的,ASCII,而不是ANSI等),所以在这种情况下,编码对我来说不是问题。
答案 0 :(得分:82)
您在评论Calum的回答中说明了您将要使用
CharStreams.toString(new InputStreamReader(supplier.get(), Charsets.UTF_8))
此代码存在问题,因为重载CharStreams.toString(Readable)
表示:
不关闭
Readable
。
这意味着,此代码完成后,您的InputStreamReader
以及InputStream
返回的supplier.get()
将不会被关闭。
另一方面,如果您利用了似乎已经拥有InputSupplier<InputStream>
并使用了重载CharStreams.toString(InputSupplier<R extends Readable & Closeable>
)的事实,那么toString
方法将同时处理为您创建和关闭Reader
。
这正是Jon Skeet所建议的,除了CharStreams.newReaderSupplier
实际上没有任何重载需要InputStream
作为输入...你必须给它一个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));
远比这更简洁:
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中弃用。他们的替换是ByteSource
,CharSource
,ByteSink
和CharSink
。给定ByteSource
,您现在可以将其内容设为String
,如下所示:
ByteSource source = ...
String text = source.asCharSource(Charsets.UTF_8).read();
答案 1 :(得分:55)
如果您有Readable
,则可以使用CharStreams.toString(Readable)
。所以你可以做以下事情:
String string = CharStreams.toString( new InputStreamReader( inputStream, "UTF-8" ) );
强制你指定一个字符集,我猜你应该这样做。
答案 2 :(得分:15)
近。你可以使用这样的东西:
InputSupplier<InputStreamReader> readerSupplier = CharStreams.newReaderSupplier
(streamSupplier, Charsets.UTF_8);
String text = CharStreams.toString(readerSupplier);
我个人不认为IOUtils.toString(InputStream)
“很好” - 因为它总是使用平台的默认编码,这几乎不是你想要的。有一个重载,它采用编码的名称,但使用名称不是一个好主意IMO。这就是我喜欢Charsets.*
的原因。
编辑:并非上述内容需要InputSupplier<InputStream>
作为streamSupplier
。如果你已经有了这个流,你可以很容易地实现它:
InputSupplier<InputStream> supplier = new InputSupplier<InputStream>() {
@Override public InputStream getInput() {
return stream;
}
};
答案 3 :(得分:15)
更新:回顾过去,我不喜欢旧的解决方案。除了它现在是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);
}
答案 4 :(得分:12)
另一种选择是从Stream读取字节并从中创建一个字符串:
new String(ByteStreams.toByteArray(inputStream))
new String(ByteStreams.toByteArray(inputStream), Charsets.UTF_8)
它不是纯粹的&#39;番石榴,但它有点短。
答案 5 :(得分:4)
根据接受的答案,这里有一个实用工具方法,可以模仿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);
}
}
答案 6 :(得分:3)
如果输入流来自类路径资源,则有更短的自动关闭解决方案:
URL resource = classLoader.getResource(path);
byte[] bytes = Resources.toByteArray(resource);
String text = Resources.toString(resource, StandardCharsets.UTF_8);
使用由Resources启发的番石榴IOExplained。
答案 7 :(得分:2)
编辑(2015):Okio是我所知道的Java / Android中I / O的最佳抽象和工具。我一直都在使用它。
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));
答案 8 :(得分:0)
有关具体示例,请参阅我在何处阅读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;
}