8

我需要将 InputStream 的内容转换为字符串。这里的难点在于输入编码,即Latin-1。我尝试了几种使用 String、getBytes、char[] 等的方法和代码片段,以便直接进行编码,但似乎没有任何效果。

最后,我想出了下面的工作解决方案。但是,这段代码对我来说似乎有点冗长,即使对于 Java 也是如此。所以这里的问题是:

是否有更简单、更优雅的方法来实现这里所做的事情?

private String convertStreamToStringLatin1(java.io.InputStream is)
        throws IOException {

    String text = "";

    // setup readers with Latin-1 (ISO 8859-1) encoding
    BufferedReader i = new BufferedReader(new InputStreamReader(is, "8859_1"));

    int numBytes;
    CharBuffer buf = CharBuffer.allocate(512);
    while ((numBytes = i.read(buf)) != -1) {
        text += String.copyValueOf(buf.array(), 0, numBytes);
        buf.clear();
    }

    return text;
}
4

5 回答 5

7

首先,对您已经采取的方法提出了一些批评。当您只CharBuffer想要一个char[512]. 您也不需要clear每次迭代都缓冲。

int numBytes;
final char[] buf = new char[512];
while ((numBytes = i.read(buf)) != -1) {
    text += String.copyValueOf(buf, 0, numBytes);
}

您还应该知道,仅使用这些参数构造 aString将具有相同的效果,因为构造函数也会复制数据。

子数组的内容被复制;随后对字符数组的修改不会影响新创建的字符串。


您可以使用动态ByteArrayOutputStream增长内部缓冲区来容纳所有数据。然后,您可以使用整个byte[]fromtoByteArray解码为String.

这样做的好处是,将解码延迟到最后可以避免单独解码片段;虽然这可能适用于 ASCII 或 ISO-8859-1 等简单字符集,但不适用于 UTF-8 和 UTF-16 等多字节方案。这意味着将来更改字符编码更容易,因为代码不需要修改。

private static final String DEFAULT_ENCODING = "ISO-8859-1";

public static final String convert(final InputStream in) throws IOException {
  return convert(in, DEFAULT_ENCODING);
}

public static final String convert(final InputStream in, final String encoding) throws IOException {
  final ByteArrayOutputStream out = new ByteArrayOutputStream();
  final byte[] buf = new byte[2048];
  int rd;
  while ((rd = in.read(buf, 0, 2048) >= 0) {
    out.write(buf, 0, rd);
  }
  return new String(out.toByteArray(), 0, encoding);
}
于 2012-08-07T22:29:32.317 回答
3

我不明白它怎么可能更简单。我做了一次有点不同..如果你已经有一个字符串,你可以这样做:

new String(originalString.getBytes(), "ISO-8859-1");

所以这样的事情也可以工作:

BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
  sb.append(line + "\n");
}
is.close();
return new String(sb.toString().getBytes(), "ISO-8859-1");

编辑:我应该补充一点,这实际上只是您已经工作的解决方案的替代方案。当谈到在 Java 中转换 Streams 时,它不会简单得多,所以去吧。:)

于 2012-08-07T22:20:38.727 回答
0

如果您不想自己动手,您可以查看 apache commons io 项目IOUtils.toString(InputStream input, String encoding),它似乎可以满足您的需求。我自己没有尝试过这种方法,但是 java 文档指出“使用指定的字符编码将 InputStream 的内容作为字符串获取”。

于 2012-08-07T22:32:10.827 回答
0

Guava的 IO 包以这种方式非常好。

Files.toString(yourFile, CharSets.ISO_8859_1)

或来自流

new String(ByteStreams.toByteArray(stream), CharSets.ISO_8859_1)
于 2012-08-07T22:41:32.697 回答
0

我刚刚发现这个问题的答案Read/convert an InputStream to a String可以应用于我的问题,请参阅下面的代码。无论如何,我非常感谢您迄今为止给出的答案。

private String convertStreamToString(InputStream is, String charsetName) {
    try {
        return new java.util.Scanner(is, charsetName).useDelimiter("\\A").next();
    } catch (java.util.NoSuchElementException e) {
        return "";
    }
}

所以为了从 Latin-1 编码,这样称呼它:

String message = convertStreamToString(is, "8859_1");
于 2012-08-07T22:44:06.837 回答