Java:将字符串列表作为InputStream访问

时间:2012-03-23 10:38:47

标签: java java-io

InputStream包装UTF-8 String列表的方式吗?我想做点什么:

InputStream in = new XyzInputStream( List<String> lines )

7 个答案:

答案 0 :(得分:8)

您可以阅读ByteArrayOutputStream,然后使用byte[]创建源ByteArrayInputStream数组。

所以按如下方式创建数组:

 List<String> source = new ArrayList<String>();
 source.add("one");
 source.add("two");
 source.add("three");
 ByteArrayOutputStream baos = new ByteArrayOutputStream();

 for (String line : source) {
   baos.write(line.getBytes());
 }

 byte[] bytes = baos.toByteArray();

从中读取就像:

 InputStream in = new ByteArrayInputStream(bytes);

或者,根据您的目标,StringReader可能会更好。

答案 1 :(得分:4)

简而言之,不,没有办法使用现有的JDK类来实现这一点。但是,您可以实现从字符串列表中读取的自己的InputStream

编辑:Dave Web上面有一个答案,我认为这是要走的路。如果你需要一个可重用的类,那么这样的事情可能会:


public class StringsInputStream<T extends Iterable<String>> extends InputStream {

   private ByteArrayInputStream bais = null;

   public StringsInputStream(final T strings) throws IOException {
      ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
      for (String line : strings) {
         outputStream.write(line.getBytes());
      }
      bais = new ByteArrayInputStream(outputStream.toByteArray());
   }

   @Override
   public int read() throws IOException {
      return bais.read();
   }

   @Override
   public int read(byte[] b) throws IOException {
      return bais.read(b);
   }

   @Override
   public int read(byte[] b, int off, int len) throws IOException {
      return bais.read(b, off, len);
   }

   @Override
   public long skip(long n) throws IOException {
      return bais.skip(n);
   }

   @Override
   public int available() throws IOException {
      return bais.available();
   }

   @Override
   public void close() throws IOException {
      bais.close();
   }

   @Override
   public synchronized void mark(int readlimit) {
      bais.mark(readlimit);
   }

   @Override
   public synchronized void reset() throws IOException {
      bais.reset();
   }

   @Override
   public boolean markSupported() {
      return bais.markSupported();
   }

   public static void main(String[] args) throws Exception {
      List source = new ArrayList();
      source.add("foo ");
      source.add("bar ");
      source.add("baz");

      StringsInputStream<List<String>> in = new StringsInputStream<List<String>>(source);

      int read = in.read();
      while (read != -1) {
         System.out.print((char) read);
         read = in.read();
      }
   }
}

这基本上是ByteArrayInputStream的适配器。

答案 2 :(得分:3)

您可以将所有行连接在一起以创建String,然后使用String#getBytes将其转换为字节数组,并将其传递给ByteArrayInputStream。然而,这不是最有效的方法。

答案 3 :(得分:0)

您也可以这样创建可序列化列表

List<String> quarks = Arrays.asList(
      "up", "down", "strange", "charm", "top", "bottom"
    );

//serialize the List
//note the use of abstract base class references

try{
  //use buffering
  OutputStream file = new FileOutputStream( "quarks.ser" );
  OutputStream buffer = new BufferedOutputStream( file );
  ObjectOutput output = new ObjectOutputStream( buffer );
  try{
    output.writeObject(quarks);
  }
  finally{
    output.close();
  }
}  
catch(IOException ex){
  fLogger.log(Level.SEVERE, "Cannot perform output.", ex);
}

//deserialize the quarks.ser file
//note the use of abstract base class references

try{
  //use buffering
  InputStream file = new FileInputStream( "quarks.ser" );
  InputStream buffer = new BufferedInputStream( file );
  ObjectInput input = new ObjectInputStream ( buffer );
  try{
    //deserialize the List
    List<String> recoveredQuarks = (List<String>)input.readObject();
    //display its data
    for(String quark: recoveredQuarks){
      System.out.println("Recovered Quark: " + quark);
    }
  }
  finally{
    input.close();
  }
}
catch(ClassNotFoundException ex){
  fLogger.log(Level.SEVERE, "Cannot perform input. Class not found.", ex);
}
catch(IOException ex){
  fLogger.log(Level.SEVERE, "Cannot perform input.", ex);
}

答案 4 :(得分:0)

你可以做类似的事情:

https://commons.apache.org/sandbox/flatfile/xref/org/apache/commons/flatfile/util/ConcatenatedInputStream.html

它只实现了InputStream的read()方法,并且有一个连接的InputStream列表。一旦读取EOF,它就会从下一个InputStream开始读取。只需将字符串转换为ByteArrayInputStreams。

答案 5 :(得分:0)

您可以创建某种IterableInputStream

public class IterableInputStream<T> extends InputStream {

    public static final int EOF = -1;

    private static final InputStream EOF_IS = new InputStream() {
        @Override public int read() throws IOException {
            return EOF;
        }
    };

    private final Iterator<T> iterator;
    private final Function<T, byte[]> mapper;

    private InputStream current;

    public IterableInputStream(Iterable<T> iterable, Function<T, byte[]> mapper) {
        this.iterator = iterable.iterator();
        this.mapper = mapper;
        next();
    }

    @Override
    public int read() throws IOException {
        int n = current.read();
        while (n == EOF && current != EOF_IS) {
            next();
            n = current.read();
        }
        return n;
    }

    private void next() {
        current = iterator.hasNext() 
            ? new ByteArrayInputStream(mapper.apply(iterator.next())) 
            : EOF_IS;
    }
}

要使用它

public static void main(String[] args) throws IOException {
    Iterable<String> strings = Arrays.asList("1", "22", "333", "4444");
    try (InputStream is = new IterableInputStream<String>(strings, String::getBytes)) {
        for (int b = is.read(); b != -1; b = is.read()) {
            System.out.print((char) b);
        }
    }
}    

答案 6 :(得分:0)

就我而言,我必须转换等效文件中的字符串列表(每行换行)。

这是我的解决方案:

List<String> inputList = Arrays.asList("line1", "line2", "line3");

byte[] bytes = inputList.stream().collect(Collectors.joining("\n")).getBytes();

InputStream inputStream = new ByteArrayInputStream(bytes);