String
として使用したいInputStream
があります。 Java 1.0では、 _Java.io.StringBufferInputStream
_ を使用できますが、それは_@Deprecrated
_(正当な理由-文字セットのエンコードを指定できません):
このクラスは、文字をバイトに適切に変換しません。 JDK 1.1以降、文字列からストリームを作成する好ましい方法は
StringReader
クラスを使用することです。
_Java.io.Reader
_ と _Java.io.StringReader
_ を作成できますが、Reader
およびInputStream
を作成します。
古代のバグ を見つけて、適切な代替品を求めましたが、そのようなものは存在しません-私が知る限りです。
よく推奨される回避策は、 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
全体をバイトの配列として具体化することを意味し、ストリームの目的を無効にします。ほとんどの場合、これは大したことではありませんが、ストリームの意図を保存するものを探していました-可能な限り少ないデータがメモリに(再)実体化されます。
更新:この回答は、OPが望んでいないものです。他の答えを読んでください。
データがメモリに再実体化されることを気にしない場合は、次を使用してください:
new ByteArrayInputStream(str.getBytes("UTF-8"))
commons-io パッケージへの依存関係を気にしない場合は、 IOUtils.toInputStream(String text) メソッドを使用できます。
Readerから ReaderInputStream という名前のInputStreamに適応するApache Commons-IOのアダプターがあります。
サンプルコード:
@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));
}
私の考えでは、これを行う最も簡単な方法は、ライターを介してデータをプッシュすることです。
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のチャンクで使用しますが、一度に書き込まれる文字数を減らしてフラッシュを呼び出すことで、バッファーサイズに影響を与える可能性があります。
Writerを使用してデータをエンコードする独自のCharsetEncoderラッパーを作成する代わりに、適切に行うのは面倒です。これは、信頼できる(非効率的である場合)実装である必要があります。
/** 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);
}
}
}
さて、1つの可能な方法は:
PipedOutputStream
を作成しますPipedInputStream
OutputStreamWriter
をPipedOutputStream
の周りにラップします(コンストラクターでエンコードを指定できます)OutputStreamWriter
に書き込むものはすべてPipedInputStream
から読み取ることができます!もちろん、これはややハック的な方法のように見えますが、少なくとも方法です。
解決策は、独自のロールを作成し、Java.nio.charset.CharsetEncoder
を使用して各InputStream
またはchar
sのチャンクをバイト配列にエンコードするchar
実装を作成することです。必要に応じてInputStream
.
私はこれが古い質問であることを知っていますが、今日私は同じ問題を抱えていました。これが私の解決策でした:
public static InputStream getStream(final CharSequence charSequence) {
return new InputStream() {
int index = 0;
int length = charSequence.length();
@Override public int read() throws IOException {
return index>=length ? -1 : charSequence.charAt(index++);
}
};
}
Org.hsqldb.libライブラリの助けを借りることができます。
public StringInputStream(String paramString)
{
this.str = paramString;
this.available = (paramString.length() * 2);
}