简体   繁体   English

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

[英]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. InputSupplierOutputSupplier以及使用它们的方法已在Guava 16.0中弃用。 Their replacements are ByteSource , CharSource , ByteSink and CharSink . 他们的替代品是ByteSourceCharSourceByteSinkCharSink 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.

相关问题 IOUtils.toString需要很长时间 - IOUtils.toString taking to long JAVA使用IOUtils.toString和HttpEntity.getContent()将InputStream转换为null - JAVA Using IOUtils.toString with HttpEntity.getContent() converting the InputStream to null 大型流的IOUtils.toString()的替代方法? - Alternative to IOUtils.toString() for large streams? 要使用 IOUtils.toString() 导入什么? - What to import to use IOUtils.toString()? IOUtils.toString() 异常 java.net.SocketTimeoutException: null - IOUtils.toString() exception java.net.SocketTimeoutException: null 在使用commons-io的IOUtils.toString(输入)后,是否需要手动关闭输入流? - Do I need to close the input stream manually after using IOUtils.toString(input) of commons-io? 使用 `IOUtils.toString(containerRequestContext.getEntityStream(),“UTF-8”); 时无法解码特殊字符 ` - Cannot decode special character when using `IOUtils.toString(containerRequestContext.getEntityStream(),“UTF-8”); ` 在 Java 中,如何使用 Google 的 guava CharStreams.toString 进程中的 inputStream? - In Java, how can I use the inputStream from a process with Google's guava CharStreams.toString? IOUtils.read()之后InputStream会发生什么 - What happens to InputStream after IOUtils.read() 对于IOUtils类型,未定义方法toByteArray(InputStream) - The method toByteArray(InputStream) is undefined for the type IOUtils
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM