我怎样才能从java.lang.String获得java.io.InputStream?
我有一个String
,我想用作一个InputStream
。 在Java 1.0中,你可以使用java.io.StringBufferInputStream
,但是已经被@Deprecrated
(有很好的理由 – 你不能指定字符集编码):
这个类不能正确地将字符转换为字节。 从JDK 1.1开始,从string创buildstream的首选方法是通过
StringReader
类。
您可以使用java.io.StringReader
创build一个java.io.Reader
,但是没有适配器需要Reader
并创build一个InputStream
。
我发现一个古老的虫子要求一个合适的替代品,但是根本没有这样的东西存在 – 据我所知。
build议的解决方法是使用java.lang.String.getBytes()
作为java.io.ByteArrayInputStream
input:
public InputStream createInputStream(String s, String charset) throws java.io.UnsupportedEncodingException { return new ByteArrayInputStream(s.getBytes(charset)); }
但是这意味着在内存中将整个String
实现为字节数组,并且破坏了stream的目的。 在大多数情况下,这不是什么大不了的事情,但是我一直在寻找能够保留stream的意图的东西 – 尽可能less的数据在内存中实现。
更新:这个答案正是OP不想要的。 请阅读其他答案。
对于那些不关心内存中重新实现的数据的情况,请使用:
new ByteArrayInputStream(str.getBytes("UTF-8"))
如果你不介意对commons-io包的依赖,那么你可以使用IOUtils.toInputStream(String text)方法。
在我看来,最简单的方法是通过Writer推送数据:
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块的forms推送数据,但通过减less一次写入的字符数和调用flush,可能会影响缓冲区的大小。
另一种方法是编写自己的CharsetEncoder包装器来使用Writer对数据进行编码,尽pipe这样做是很痛苦的。 这应该是一个可靠(如果效率低下)的实现:
/** 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); } } }
Apache Commons-IO有一个适配器,可以从Reader 调用到InputStream,它被命名为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
那么,一个可能的方法是:
- 创build一个
PipedOutputStream
- 将其pipe理到
PipedInputStream
- 将一个
OutputStreamWriter
在PipedOutputStream
周围(可以在构造函数中指定编码) - 除此之外,您可以从
PipedInputStream
读取任何写入OutputStreamWriter
的内容!
当然,这似乎是一个相当黑客的做法,但至less这是一种方式。
一个解决scheme就是自己创build一个InputStream
实现,它可能会使用java.nio.charset.CharsetEncoder
来根据需要将每个char
或char
的块编码为InputStream
一个字节数组。
我知道这是一个古老的问题,但我今天也有同样的问题,这是我的解决scheme:
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); }