如何从 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 20:02:50  来源:igfitidea点击:

How can I get a java.io.InputStream from a java.lang.String?

javastringinputstream

提问by Jared Oberhaus

I have a Stringthat 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 StringReaderclass.

此类未正确将字符转换为字节。从 JDK 1.1 开始,从字符串创建流的首选方法是通过StringReader类。

You can create a java.io.Readerwith java.io.StringReader, but there are no adapters to take a Readerand create an InputStream.

您可以创建java.io.Readerwith 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 Stringin 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:

好吧,一种可能的方法是:

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 InputStreamimplementation that likely would use java.nio.charset.CharsetEncoderto encode each charor chunk of chars to an array of bytes for the InputStreamas 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

参考: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);
  }