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

コンストラクターもデータをコピーするため、これらの引数を使用してa を構築するStringだけでも同じ効果があることも知っておく必要があります。

サブ配列の内容がコピーされます。文字配列を後で変更しても、新しく作成された文字列には影響しません。


ByteArrayOutputStreamすべてのデータに対応するために内部バッファーを拡張する動的を使用できます。byte[]次に、 from全体を使用しtoByteArrayて にデコードでき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

InputStream を文字列に読み取り/変換するという質問に対するこの回答が私の問題に適用できることがわかりました。以下のコードを参照してください。とにかく、これまでにあなたが与えてくれた答えにとても感謝しています。

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 に答える
0

自分で配管したくない場合は、apache commons io プロジェクトIOUtils.toString(InputStream input, String encoding)を見てください。これは、あなたが望むことをしているようです。私はその方法を自分で試したことはありませんが、Java ドキュメントには、「指定された文字エンコーディングを使用して、InputStream の内容を文字列として取得する」と記載されています。

于 2012-08-07T22:32:10.827 に答える