如何从 java.lang.String 获取 java.io.InputStream?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/837703/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I get a java.io.InputStream from a java.lang.String?
提问by Jared Oberhaus
I have a String
that I want to use as an InputStream
. In Java 1.0, you could use java.io.StringBufferInputStream
, but that has been @Deprecrated
(with good reason--you cannot specify the character set encoding):
我有一个String
我想用作InputStream
. 在 Java 1.0 中,您可以使用java.io.StringBufferInputStream
,但这已经是@Deprecrated
(有充分的理由——您不能指定字符集编码):
This class does not properly convert characters into bytes. As of JDK 1.1, the preferred way to create a stream from a string is via the
StringReader
class.
此类未正确将字符转换为字节。从 JDK 1.1 开始,从字符串创建流的首选方法是通过
StringReader
类。
You can create a java.io.Reader
with java.io.StringReader
, but there are no adapters to take a Reader
and create an InputStream
.
您可以创建java.io.Reader
with java.io.StringReader
,但没有适配器可以使用 aReader
并创建InputStream
.
I found an ancient bugasking for a suitable replacement, but no such thing exists--as far as I can tell.
我发现了一个古老的错误,需要一个合适的替代品,但据我所知,不存在这样的东西。
The oft-suggested workaround is to use java.lang.String.getBytes()
as input to java.io.ByteArrayInputStream
:
经常建议的解决方法是java.lang.String.getBytes()
用作输入java.io.ByteArrayInputStream
:
public InputStream createInputStream(String s, String charset)
throws java.io.UnsupportedEncodingException {
return new ByteArrayInputStream(s.getBytes(charset));
}
but that means materializing the entire String
in memory as an array of bytes, and defeats the purpose of a stream. In most cases this is not a big deal, but I was looking for something that would preserve the intent of a stream--that as little of the data as possible is (re)materialized in memory.
但这意味着将整个String
内存具体化为一个字节数组,并违背了流的目的。在大多数情况下,这没什么大不了的,但我一直在寻找可以保留流意图的东西——尽可能少的数据在内存中(重新)具体化。
回答by Michael Myers
Well, one possible way is to:
好吧,一种可能的方法是:
- Create a
PipedOutputStream
- Pipe it to a
PipedInputStream
- Wrap an
OutputStreamWriter
around thePipedOutputStream
(you can specify the encoding in the constructor) - Et voilá, anything you write to the
OutputStreamWriter
can be read from thePipedInputStream
!
- 创建一个
PipedOutputStream
- 管道它到一个
PipedInputStream
- 一个包裹
OutputStreamWriter
周围的PipedOutputStream
(可以指定在构造函数中的编码) - 等等,您写入的任何内容
OutputStreamWriter
都可以从PipedInputStream
!
Of course, this seems like a rather hackish way to do it, but at least it is a way.
当然,这似乎是一种相当骇人听闻的方法,但至少它是一种方法。
回答by Jared Oberhaus
A solution is to roll your own, creating an InputStream
implementation that likely would use java.nio.charset.CharsetEncoder
to encode each char
or chunk of char
s to an array of bytes for the InputStream
as necessary.
一个解决方案是自己动手,创建一个InputStream
实现,该实现可能用于根据需要将s 的java.nio.charset.CharsetEncoder
每个char
或块编码char
为字节数组InputStream
。
回答by McDowell
To my mind, the easiest way to do this is by pushing the data through a Writer:
在我看来,最简单的方法是通过 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();
}
}
The JVM implementation I'm using pushed data through in 8K chunks, but you could have some affect on the buffer size by reducing the number of characters written at one time and calling flush.
我使用的 JVM 实现以 8K 块的形式推送数据,但是通过减少一次写入的字符数并调用flush,您可能会对缓冲区大小产生一些影响。
An alternative to writing your own CharsetEncoder wrapper to use a Writer to encode the data, though it is something of a pain to do right. This should be a reliable (if inefficient) implementation:
编写您自己的 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);
}
}
}
回答by Fotis Paraskevopoulos
If you don't mind a dependency on the commons-iopackage, then you could use the IOUtils.toInputStream(String text)method.
如果您不介意依赖于commons-io包,那么您可以使用IOUtils.toInputStream(String text)方法。
回答by Andres Riofrio
Update:This answer is precisely what the OP doesn't want. Please read the other answers.
更新:这个答案正是 OP 不想要的。请阅读其他答案。
For those cases when we don't care about the data being re-materialized in memory, please use:
对于那些我们不关心在内存中重新物化数据的情况,请使用:
new ByteArrayInputStream(str.getBytes("UTF-8"))
回答by Paul Richards
I know this is an old question but I had the same problem myself today, and this was my solution:
我知道这是一个老问题,但今天我自己也遇到了同样的问题,这是我的解决方案:
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++);
}
};
}
回答by beat
There is an adapter from Apache Commons-IO which adapts from Reader to InputStream, which is named ReaderInputStream.
Apache Commons-IO 有一个适配器,它从 Reader 适配到 InputStream,它被命名为ReaderInputStream。
Example code:
示例代码:
@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));
}
Reference: https://stackoverflow.com/a/27909221/5658642
回答by omar
You can take help of org.hsqldb.lib library.
您可以借助 org.hsqldb.lib 库。
public StringInputStream(String paramString)
{
this.str = paramString;
this.available = (paramString.length() * 2);
}