Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从java.lang.String获取java.io.InputStream?_Java_String_Inputstream - Fatal编程技术网

如何从java.lang.String获取java.io.InputStream?

如何从java.lang.String获取java.io.InputStream?,java,string,inputstream,Java,String,Inputstream,我有一个字符串,我想用作输入流。在Java 1.0中,您可以使用,但这已经被@Deprecrated(有充分的理由——您不能指定字符集编码): 此类不能正确转换 将字符转换为字节。从JDK 1.1开始, 创建流的首选方法 通过StringReader 班级 您可以使用创建,但没有适配器可以使用读取器和创建输入流 我找到了一个合适的替代品,但据我所知,没有这样的东西存在 oft建议的解决方法是将其用作输入: 但这意味着将整个字符串在内存中具体化为一个字节数组,从而破坏了流的用途。在大多数情况下,这

我有一个
字符串
,我想用作
输入流
。在Java 1.0中,您可以使用,但这已经被
@Deprecrated
(有充分的理由——您不能指定字符集编码):

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

您可以使用创建,但没有适配器可以使用
读取器
和创建
输入流

我找到了一个合适的替代品,但据我所知,没有这样的东西存在

oft建议的解决方法是将其用作输入:


但这意味着将整个
字符串
在内存中具体化为一个字节数组,从而破坏了流的用途。在大多数情况下,这没什么大不了的,但我一直在寻找能够保留流意图的东西——尽可能少的数据在内存中(重新)具体化。

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

  • 创建一个
  • 把它输送到一个管道里
  • 围绕
    管道输出流
    (您可以在构造函数中指定编码)包装一个
  • 等等,您向
    OutputStreamWriter
    写入的任何内容都可以从
    PipedInputStream
    读取

当然,这似乎是一种相当粗俗的方式,但至少是一种方式。

一种解决方案是自己动手,创建一个
InputStream
实现,该实现可能会使用
java.nio.charset.CharsetEncoder
将每个
char
char
块编码为
InputStream
的字节数组。在我看来,最简单的方法是通过编写器将数据推送到:

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();
  }
}
公共类字符串发射器{
公共静态void main(字符串[]args)引发IOException{
类DataHandler扩展OutputStream{
@凌驾
public void write(final int b)引发IOException{
写入(新字节[]{(字节)b});
}
@凌驾
公共无效写入(字节[]b)引发IOException{
写入(b,0,b.长度);
}
@凌驾
公共无效写入(字节[]b,int off,int len)
抛出IOException{
System.out.println(“字节计数=”+len);
}
}
StringBuilder示例=新建StringBuilder();
while(sample.length()<100*1000){
样本。附加(“样本”);
}
Writer Writer=新输出流Writer(
新的DataHandler(),“UTF-16”);
writer.write(sample.toString());
writer.close();
}
}
我正在使用的JVM实现以8K块的形式推送数据,但是通过减少一次写入的字符数并调用flush,可以对缓冲区大小产生一些影响


编写自己的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);
    }

  }

}
/**低效的字符串流实现*/
公共类StringInputStream扩展了InputStream{
/*#要缓冲的字符数-必须大于等于2才能处理代理项对*/
专用静态最终int CHAR_CAP=8;
私有最终队列缓冲区=新的LinkedList();
专用终端机编码器;
私有最终字符串数据;
私有整数索引;
公共StringInputStream(字符串序列,字符集字符集){
数据=序列;
编码器=新的OutputStreamWriter(
新的OutputStreamBuffer(),字符集);
}
private int buffer()引发IOException{
如果(索引>=data.length()){
返回-1;
}
int rlen=索引+字符上限;
如果(rlen>data.length()){
rlen=data.length();
}
对于(;索引=data.length()){
encoder.close();
}
返回buffer.size();
}
@凌驾
public int read()引发IOException{
if(buffer.size()==0){
int r=buffer();
如果(r==-1){
返回-1;
}
}
返回0xFF&buffer.remove();
}
私有类OutputStreamBuffer扩展了OutputStream{
@凌驾
公共无效写入(int i)引发IOException{
字节b=(字节)i;
添加(b);
}
}
}

如果你不介意对包的依赖,那么你可以使用这个方法。

更新:这个答案正是OP不想要的。请阅读其他答案

对于那些我们不关心数据在内存中重新具体化的情况,请使用:

new ByteArrayInputStream(str.getBytes("UTF-8"))

我知道这是一个老问题,但今天我自己也遇到了同样的问题,这就是我的解决方案:

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++);
  }
 };
}

有一个来自ApacheCommonsIO的适配器,它从读取器适配到InputStream,名为

示例代码:

@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));
}

参考资料:

您可以向org.hsqldb.lib库寻求帮助

public StringInputStream(String paramString)
  {
    this.str = paramString;
    this.available = (paramString.length() * 2);
  }

有趣的。。。当然,有了这个解决方案,我相信你要么在内存中具体化整个字符串,要么在阅读线程中忍受饥饿。仍然希望在某个地方有一个真正的实现。您必须小心使用管道(输入|输出)流。根据文档:“不建议尝试从单个线程使用两个对象,因为这可能会使线程死锁…”一次只执行一个字符的操作成本很高。这就是为什么我们有“分块迭代器”,比如InputStream,它允许我们一次读取一个缓冲区。我同意Tom的观点——你真的不想一次读取一个字符。除非数据非常小,其他事情(例如网络延迟)需要更长的时间。那就没关系了。:)在这种情况下,您添加了一个依赖项,它除了“返回新的ByteArrayInputStream(input.getBytes());”之外什么都不做这真的值得依赖吗?老实说,不是我
public StringInputStream(String paramString)
  {
    this.str = paramString;
    this.available = (paramString.length() * 2);
  }