[英]Guava equivalent for IOUtils.toString(InputStream)
Apache Commons IO has a nice convenience method IOUtils.toString() to read an InputStream
to a String. Apache Commons IO有一个很好的方便方法IOUtils.toString()来将InputStream
读取到String。
Since I am trying to move away from Apache Commons and to Guava : is there an equivalent in Guava? 因为我试图从Apache Commons转移到Guava :在番石榴中是否有相同的东西? I looked at all classes in the com.google.common.io
package and I couldn't find anything nearly as simple. 我查看了com.google.common.io
包中的所有类,我找不到任何简单的东西。
Edit: I understand and appreciate the issues with charsets. 编辑:我理解并欣赏charsets的问题。 It just so happens that I know that all my sources are in ASCII (yes, ASCII, not ANSI etc.), so in this case, encoding is not an issue for me. 事实上,我知道所有的源都是ASCII(是的,ASCII,而不是ANSI等),所以在这种情况下,编码对我来说不是问题。
You stated in your comment on Calum's answer that you were going to use 您在评论Calum的回答中说明了您将要使用的内容
CharStreams.toString(new InputStreamReader(supplier.get(), Charsets.UTF_8))
This code is problematic because the overload CharStreams.toString(Readable)
states: 此代码存在问题,因为重载CharStreams.toString(Readable)
指出:
Does not close the
Readable
. 不关闭Readable
。
This means that your InputStreamReader
, and by extension the InputStream
returned by supplier.get()
, will not be closed after this code completes. 这意味着在此代码完成后,您的InputStreamReader
以及supplier.get()
返回的InputStream
将不会被关闭。
If, on the other hand, you take advantage of the fact that you appear to already have an InputSupplier<InputStream>
and used the overload CharStreams.toString(InputSupplier<R extends Readable & Closeable>
), the toString
method will handle both the creation and closing of the Reader
for you. 另一方面,如果你利用了一个事实,你似乎已经有了一个InputSupplier<InputStream>
并使用了重载CharStreams.toString(InputSupplier<R extends Readable & Closeable>
),那么toString
方法将处理这两个创建并为您关闭Reader
。
This is exactly what Jon Skeet suggested, except that there isn't actually any overload of CharStreams.newReaderSupplier
that takes an InputStream
as input... you have to give it an InputSupplier
: 这正是乔恩斯基特建议,但没有真正的任何超载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);
The point of InputSupplier
is to make your life easier by allowing Guava to handle the parts that require an ugly try-finally
block to ensure that resources are closed properly. InputSupplier
是通过允许Guava处理需要丑陋的try-finally
块的部分来确保资源正确关闭,从而使您的生活更轻松。
Edit: Personally, I find the following (which is how I'd actually write it, was just breaking down the steps in the code above) 编辑:就个人而言,我发现以下(这是我实际编写它的方式,只是打破了上面代码中的步骤)
String text = CharStreams.toString(
CharStreams.newReaderSupplier(supplier, Charsets.UTF_8));
to be far less verbose than this: 要远远比这个更简洁:
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);
}
Which is more or less what you'd have to write to handle this properly yourself. 这或多或少是你必须写的,以便自己妥善处理。
Edit: Feb. 2014 编辑:2014年2月
InputSupplier
and OutputSupplier
and the methods that use them have been deprecated in Guava 16.0. InputSupplier
和OutputSupplier
以及使用它们的方法已在Guava 16.0中弃用。 Their replacements are ByteSource
, CharSource
, ByteSink
and CharSink
. 他们的替代品是ByteSource
, CharSource
, ByteSink
和CharSink
。 Given a ByteSource
, you can now get its contents as a String
like this: 给定一个ByteSource
,您现在可以将其内容作为String
如下所示:
ByteSource source = ...
String text = source.asCharSource(Charsets.UTF_8).read();
If you've got a Readable
you can use CharStreams.toString(Readable)
. 如果你有一个Readable
你可以使用CharStreams.toString(Readable)
。 So you can probably do the following: 所以你可以做以下事情:
String string = CharStreams.toString( new InputStreamReader( inputStream, "UTF-8" ) );
Forces you to specify a character set, which I guess you should be doing anyway. 强制你指定一个字符集,我猜你应该这样做。
UPDATE : Looking back, I don't like my old solution. 更新 :回顾过去,我不喜欢我的旧解决方案。 Besides it is 2013 now and there are better alternatives available now for Java7. 除了它现在是2013年,Java7现在有更好的替代品。 So here is what I use now: 所以我现在使用的是:
InputStream fis = ...;
String text;
try ( InputStreamReader reader = new InputStreamReader(fis, Charsets.UTF_8)){
text = CharStreams.toString(reader);
}
or if with InputSupplier 或者如果使用InputSupplier
InputSupplier<InputStreamReader> spl = ...
try ( InputStreamReader reader = spl.getInput()){
text = CharStreams.toString(reader);
}
Nearly. 几乎。 You could use something like this: 你可以使用这样的东西:
InputSupplier<InputStreamReader> readerSupplier = CharStreams.newReaderSupplier
(streamSupplier, Charsets.UTF_8);
String text = CharStreams.toString(readerSupplier);
Personally I don't think that IOUtils.toString(InputStream)
is "nice" - because it always uses the default encoding of the platform, which is almost never what you want. 我个人不认为IOUtils.toString(InputStream)
是“好” -因为它总是使用的平台,这是几乎从来没有你想要什么的默认编码。 There's an overload which takes the name of the encoding, but using names isn't a great idea IMO. 有一个重载,它采用编码的名称,但使用名称不是一个好主意IMO。 That's why I like Charsets.*
. 这就是我喜欢Charsets.*
的原因Charsets.*
。
EDIT: Not that the above needs an InputSupplier<InputStream>
as the streamSupplier
. 编辑:并不是说上面需要一个InputSupplier<InputStream>
作为streamSupplier
。 If you've already got the stream you can implement that easily enough though: 如果你已经有了这个流,你可以很容易地实现它:
InputSupplier<InputStream> supplier = new InputSupplier<InputStream>() {
@Override public InputStream getInput() {
return stream;
}
};
Another option is to read bytes from Stream and create a String from them: 另一种选择是从Stream读取字节并从中创建一个String:
new String(ByteStreams.toByteArray(inputStream))
new String(ByteStreams.toByteArray(inputStream), Charsets.UTF_8)
It's not 'pure' Guava, but it's a little bit shorter. 它不是'纯'番石榴,但它有点短。
Based on the accepted answer, here is a utility method that mocks the behavior of IOUtils.toString()
(and an overloaded version with a charset, as well). 根据接受的答案,这里有一个实用工具方法,它可以IOUtils.toString()
的行为(以及带有字符集的重载版本)。 This version should be safe, right? 这个版本应该是安全的,对吗?
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);
}
}
There is much shorter autoclosing solution in case when input stream comes from classpath resource: 如果输入流来自类路径资源,则有更短的自动关闭解决方案:
URL resource = classLoader.getResource(path);
byte[] bytes = Resources.toByteArray(resource);
String text = Resources.toString(resource, StandardCharsets.UTF_8);
Uses Guava Resources , inspired by IOExplained . 使用Guava Resources ,受IOExplained的启发。
EDIT (2015): Okio is the best abstraction and tools for I/O in Java/Android that I know of. EDIT (2015): Okio是我所知道的Java / Android中I / O的最佳抽象和工具。 I use it all the time. 我用它所有的时间。
FWIW here's what I use. FWIW这是我使用的。
If I already have a stream in hand, then: 如果我手头有一条流,那么:
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));
If I'm creating a stream: 如果我正在创建一个流:
String s = CharStreams.toString(CharStreams.newReaderSupplier(new InputSupplier<InputStream>() {
public InputStream getInput() throws IOException {
return <expression creating the stream>;
}
}, Charsets.UTF_8));
As a concrete example, I can read an Android text file asset like this: 作为一个具体的例子,我可以读取这样的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));
For a concrete example, here's how I can read an Android text file asset: 举一个具体的例子,这是我如何阅读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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.