简体   繁体   English

在 Java 中,如何使用 Google 的 guava CharStreams.toString 进程中的 inputStream?

[英]In Java, how can I use the inputStream from a process with Google's guava CharStreams.toString?

I am executing a process and want to read in its output into a String.我正在执行一个进程,并希望将其 output 读入字符串。 Rather than deal with try/catch/finally, I am hoping to use the Guava CharStreams.toString(InputSupplier<R> supplier) .我希望使用Guava CharStreams.toString(InputSupplier<R> supplier)而不是处理 try/catch/finally。 Unfortunately, the stream returned by Process's getInputStream() is type InputStream and not InputSupplier.不幸的是,Process 的getInputStream()返回的 stream 是InputStream类型,而不是 InputSupplier。 How can I use this to create an InputSupplier for use with t oString() ?如何使用它来创建InputSupplier以与 t oString()一起使用?

Ideally I could do something like this:理想情况下,我可以做这样的事情:

CharStreams.toString(CharStreams.newReaderSupplier(process.getInputStream()))

But you cannot construct an InputSupplier from an InputStream and I am having trouble finding out how to do this.但是您不能从 InputStream 构造 InputSupplier,而且我很难找出如何做到这一点。

I haven't found a way to do this with guava yet.我还没有找到用番石榴做到这一点的方法。 I am sure the developer has a good reason for this.我相信开发人员有充分的理由这样做。 The closest I have gotten without while keep it minimal is:在保持最小化的情况下,我得到的最接近的是:

 CharStreams.toString(CharStreams.newReaderSupplier(new InputSupplier<InputStream>() {
        @Override
        public InputStream getInput() throws IOException {
            return inputStream;
        }
    }, Charsets.UTF_16));

I have used newReaderSupplier from CharStreams so you don't have to wrap it with InputStreamReader .我使用newReaderSupplier的 newReaderSupplier ,所以你不必用InputStreamReader包装它。

So far this is the best I could do:到目前为止,这是我能做的最好的:

String commandOutput = CharStreams.toString(new InputSupplier<InputStreamReader>() {
    public InputStreamReader getInput() throws IOException {
        return new InputStreamReader(process.getInputStream());
    }
});

What about this:那这个呢:

CharStreams.toString(new InputStreamReader(process.getInpusttream()))

It is using CharStreams.toString(Readable) .它正在使用CharStreams.toString(Readable)

The Right Thing to Do -- and what Guava's trying to push you into doing -- is to change the code that gives you the InputStream to give you an InputSupplier instead.正确的做法——以及 Guava 试图推动你做的事情——是更改为您提供 InputStream 的代码,以改为为您提供 InputSupplier。

The reason for this is that this way, Guava gets the stream, reads the string, and closes it, and you can't accidentally use it after Guava's closed it, because you never had a reference to the InputStream in the first place.原因是这样,Guava 得到 stream,读取字符串,然后关闭它,在 Guava 关闭它之后你不能不小心使用它,因为你从来没有对 InputStream 的引用。 This eliminates a lot of potential bugs.这消除了许多潜在的错误。

The other overload, CharStreams.toString(Readable), does not close the Readable.另一个重载 CharStreams.toString(Readable) 不会关闭 Readable。 If you want to have your own, special logic for closing the input stream, this is Guava's way of letting you do that.如果您想拥有自己的特殊逻辑来关闭输入 stream,这是 Guava 让您这样做的方式。

Guava equivalent for IOUtils.toString(InputStream) says it better than I could. IOUtils.toString(InputStream) 的番石榴等价物说得比我好。

This should do it:这应该这样做:

InputStream is = process.getInputStream();
String content = CharStreams.toString(new InputStreamReader(is, Charsets.UTF_8));
is.close();

And here is a real life example of the complete usage:这是完整用法的真实示例:

HttpURLConnection connection = null;
URL url;
InputStream is = null;
try {
  url = new URL("https://graph.facebook.com/oauth/access_token?client_id=" + appId + "&client_secret=" + appSecret + "&grant_type=client_credentials");
  connection = (HttpURLConnection) url.openConnection();
  connection.setRequestProperty("accept-encoding", "gzip");

  is = connection.getInputStream();
  String content = CharStreams.toString(new InputStreamReader(is, Charsets.UTF_8));
  String[] tokens = content.split("=");
  System.out.println(tokens[1]);
} catch (IOException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
} finally {
  if (is != null) try {
    is.close();
  } catch (IOException e) {}
  connection.disconnect();
}

I know this insn't really in question, but for comparison sake he is how you'd do it with IOUtils - which IMO is a bit cleaner:我知道这并没有真正的问题,但为了比较起见,他是你用 IOUtils 做的方式——IMO 更干净一点:

HttpURLConnection connection = null;
URL url;
InputStream is = null;

try {
  url = new URL("https://graph.facebook.com/oauth/access_token?client_id=" + appId + "&client_secret=" + appSecret + "&grant_type=client_credentials");
  connection = (HttpURLConnection) url.openConnection();
  connection.setRequestProperty("accept-encoding", "gzip");

  is = connection.getInputStream();

  String value = IOUtils.toString(is);
  if (!Strings.isNullOrEmpty(value)) {
    String[] splits = value.split("=");
    System.out.println(splits[1]);
  }
} catch (IOException e) {

} finally {
  IOUtils.closeQuietly(is);
  connection.disconnect();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM