I am executing a process and want to read in its output into a String. Rather than deal wit开发者_运维知识库h try/catch/finally, I am hoping to use the Guava CharStreams.toString(InputSupplier<R> supplier)
. Unfortunately, the stream returned by Process's getInputStream()
is type InputStream
and not InputSupplier. How can I use this to create an InputSupplier
for use with toString()
?
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.
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
.
What about this:
CharStreams.toString(new InputStreamReader(process.getInpusttream()))
It is using CharStreams.toString(Readable)
.
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());
}
});
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.
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. This eliminates a lot of potential bugs.
The other overload, CharStreams.toString(Readable), does not close the 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.
Guava equivalent for IOUtils.toString(InputStream) says it better than I could.
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:
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();
}
精彩评论