IOUtils.toString(InputStream)相当于番石榴

Apache Commons IO有一个不错的方便方法IOUtils.toString()来读取一个InputStream为一个String。

由于我正试图从Apache Commons转移到Guava :在Guava中是否有相当于? 我查看了com.google.common.io包中的所有类,找不到任何简单的东西。

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

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

 CharStreams.toString(new InputStreamReader(supplier.get(), Charsets.UTF_8)) 

此代码是有问题的,因为重载CharStreams.toString(Readable)指出:

不closuresReadable

这意味着你的InputStreamReader和扩展名是由supplier.get()返回的InputStream ,在这个代码完成后将不会被closures。

另一方面,如果您利用了您似乎已经拥有InputSupplier<InputStream>并使用了重载CharStreams.toString(InputSupplier<R extends Readable & Closeable> )的CharStreams.toString(InputSupplier<R extends Readable & Closeable>toString方法将处理创build并为您closuresReader

这正是Jon Skeet所build议的,除了InputSupplier实际上没有任何以InputStream为input的重载之外,您必须给它一个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块的部分来确保资源正确closures,从而使您的生活更轻松。

编辑:个人而言,我发现以下(这是我如何写它,只是打破了上面的代码中的步骤)

 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); } 

这或多或less是你自己必须写的来处理这个问题。


编辑:2014年2月

InputSupplierOutputSupplier以及使用它们的方法已经在Guava 16.0中被弃用了。 他们的替代品是ByteSourceCharSourceByteSinkCharSink 。 给定一个ByteSource ,你现在可以像下面这样获取它的内容:

 ByteSource source = ... String text = source.asCharSource(Charsets.UTF_8).read(); 

如果你有一个Readable你可以使用CharStreams.toString(Readable) 。 所以你可以做下面的事情:

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

强制你指定一个字符集,我想你应该做的无论如何。

几乎。 你可以使用这样的东西:

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

就我个人而言,我认为IOUtils.toString(InputStream)是“很好” – 因为它总是使用平台的默认编码,这几乎从来没有你想要的。 有一个重载,它采用编码的名称,但使用名称是不是一个好主意IMO。 这就是为什么我喜欢Charsets.*

编辑:不是说上面需要一个InputSupplier<InputStream>作为streamSupplier 。 如果你已经有了这个stream,你可以很容易地实现:

 InputSupplier<InputStream> supplier = new InputSupplier<InputStream>() { @Override public InputStream getInput() { return stream; } }; 

更新 :回顾一下,我不喜欢我的旧解决scheme。 除了现在是2013年,现在有更好的select可用于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); } 

另一种select是从Stream中读取字节并从中创build一个string:

 new String(ByteStreams.toByteArray(inputStream)) new String(ByteStreams.toByteArray(inputStream), 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); } } 

在inputstream来自classpath资源的情况下,自动closures解决scheme的时间要短得多:

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

受IOExplained启发,使用番石榴资源 。

编辑 (2015): Okio是我知道的Java / Android中I / O的最佳抽象和工具。 我用它所有的时间。

FWIW这是我使用的。

如果我已经有一个stream,那么:

 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)); 

如果我正在创build一个stream:

 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)); 

举一个具体的例子,我可以读取一个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; }