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

前端 未结 8 815
悲&欢浪女
悲&欢浪女 2020-12-23 20:23

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 @Deprecra

相关标签:
8条回答
  • 2020-12-23 20:33

    To my mind, the easiest way to do this is by pushing the data through a 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.


    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:

    /** 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);
        }
    
      }
    
    }
    
    0 讨论(0)
  • 2020-12-23 20:36

    Well, one possible way is to:

    • Create a PipedOutputStream
    • Pipe it to a PipedInputStream
    • Wrap an OutputStreamWriter around the PipedOutputStream (you can specify the encoding in the constructor)
    • Et voilá, anything you write to the OutputStreamWriter can be read from the PipedInputStream!

    Of course, this seems like a rather hackish way to do it, but at least it is a way.

    0 讨论(0)
  • 2020-12-23 20:42

    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 chars to an array of bytes for the InputStream as necessary.

    0 讨论(0)
  • 2020-12-23 20:47

    Update: This answer is precisely what the OP doesn't want. Please read the other answers.

    For those cases when we don't care about the data being re-materialized in memory, please use:

    new ByteArrayInputStream(str.getBytes("UTF-8"))
    
    0 讨论(0)
  • 2020-12-23 20:47

    You can take help of org.hsqldb.lib library.

    public StringInputStream(String paramString)
      {
        this.str = paramString;
        this.available = (paramString.length() * 2);
      }
    
    0 讨论(0)
  • 2020-12-23 20:54

    If you don't mind a dependency on the commons-io package, then you could use the IOUtils.toInputStream(String text) method.

    0 讨论(0)
提交回复
热议问题