96

Stringとして使用したい がありますInputStream。Java 1.0 では を使用できjava.io.StringBufferInputStreamましたが、それは次のように行われていました@Deprecrated(正当な理由により、文字セットのエンコーディングを指定することはできません)。

このクラスは、文字を正しくバイトに変換しません。JDK 1.1 では、文字列からストリームを作成するための推奨される方法は、StringReader クラスを使用することです。

でを作成できますが、を取得java.io.Readerしてを作成するjava.io.StringReaderアダプタはありません。ReaderInputStream

適切な代替品を求める古代のバグを見つけましたが、私が知る限り、そのようなものは存在しません。

よく提案される回避策は、へjava.lang.String.getBytes()の入力として使用することjava.io.ByteArrayInputStreamです。

public InputStream createInputStream(String s, String charset)
    throws java.io.UnsupportedEncodingException {

    return new ByteArrayInputStream(s.getBytes(charset));
}

しかし、それはメモリ全体Stringをバイト配列として実体化することを意味し、ストリームの目的を無効にします。ほとんどの場合、これは大したことではありませんが、ストリームの意図を保持するもの、つまりメモリ内で (再) 実体化されるデータをできるだけ少なくするものを探していました。

4

8 に答える 8

78

更新:この答えはまさにOPが望んでいないものです。他の回答を読んでください。

データがメモリ内で再実体化されることを気にしない場合は、次を使用してください。

new ByteArrayInputStream(str.getBytes("UTF-8"))
于 2013-01-02T23:19:58.617 に答える
19

commons-ioパッケージへの依存を気にしない場合は、 IOUtils.toInputStream(String text)メソッドを使用できます。

于 2011-11-07T20:48:24.643 に答える
6

Reader から InputStream に適応する Apache Commons-IO のアダプターがあり、これはReaderInputStreamという名前です。

コード例:

@Test
public void testReaderInputStream() throws IOException {
    InputStream inputStream = new ReaderInputStream(new StringReader("largeString"), StandardCharsets.UTF_8);
    Assert.assertEquals("largeString", IOUtils.toString(inputStream, StandardCharsets.UTF_8));
}

参照: https://stackoverflow.com/a/27909221/5658642

于 2016-09-06T09:45:12.320 に答える
3

私の考えでは、これを行う最も簡単な方法は、ライターを介してデータをプッシュすることです。

public class StringEmitter {
  public static void main(String[] args) throws IOException {
    class DataHandler extends OutputStream {
      @Override
      public void write(final int b) throws IOException {
        write(new byte[] { (byte) b });
      }
      @Override
      public void write(byte[] b) throws IOException {
        write(b, 0, b.length);
      }
      @Override
      public void write(byte[] b, int off, int len)
          throws IOException {
        System.out.println("bytecount=" + len);
      }
    }

    StringBuilder sample = new StringBuilder();
    while (sample.length() < 100 * 1000) {
      sample.append("sample");
    }

    Writer writer = new OutputStreamWriter(
        new DataHandler(), "UTF-16");
    writer.write(sample.toString());
    writer.close();
  }
}

私が使用している JVM 実装では、8K チャンクでデータをプッシュしましたが、一度に書き込む文字数を減らしてフラッシュを呼び出すことで、バッファー サイズに影響を与えることができます。


独自の CharsetEncoder ラッパーを作成して Writer を使用してデータをエンコードする代わりの方法ですが、正しく行うのは面倒です。これは、(非効率的ではあるが) 信頼できる実装である必要があります。

/** Inefficient string stream implementation */
public class StringInputStream extends InputStream {

  /* # of characters to buffer - must be >=2 to handle surrogate pairs */
  private static final int CHAR_CAP = 8;

  private final Queue<Byte> buffer = new LinkedList<Byte>();
  private final Writer encoder;
  private final String data;
  private int index;

  public StringInputStream(String sequence, Charset charset) {
    data = sequence;
    encoder = new OutputStreamWriter(
        new OutputStreamBuffer(), charset);
  }

  private int buffer() throws IOException {
    if (index >= data.length()) {
      return -1;
    }
    int rlen = index + CHAR_CAP;
    if (rlen > data.length()) {
      rlen = data.length();
    }
    for (; index < rlen; index++) {
      char ch = data.charAt(index);
      encoder.append(ch);
      // ensure data enters buffer
      encoder.flush();
    }
    if (index >= data.length()) {
      encoder.close();
    }
    return buffer.size();
  }

  @Override
  public int read() throws IOException {
    if (buffer.size() == 0) {
      int r = buffer();
      if (r == -1) {
        return -1;
      }
    }
    return 0xFF & buffer.remove();
  }

  private class OutputStreamBuffer extends OutputStream {

    @Override
    public void write(int i) throws IOException {
      byte b = (byte) i;
      buffer.add(b);
    }

  }

}
于 2009-05-08T14:31:07.830 に答える
2

考えられる方法の1つは、次のとおりです。

  • 作成するPipedOutputStream
  • パイプでPipedInputStream
  • ラップOutputStreamWriterアラウンドPipedOutputStream(コンストラクターでエンコーディングを指定できます)
  • Etvoilá、あなたが書いたものは何OutputStreamWriterでもPipedInputStream

もちろん、これはかなりハックな方法のように思えますが、少なくともそれは方法です。

于 2009-05-08T00:40:54.650 に答える
1

解決策は、独自のロールを作成し、必要に応じてsの各チャンクをバイト配列にエンコードするためにInputStream使用する可能性が高い実装を作成することです。java.nio.charset.CharsetEncodercharcharInputStream

于 2009-05-08T00:52:51.300 に答える