将InputStream转换为固定长度的字符串的Stream <string>

时间:2015-05-19 21:58:50

标签: java io stream java-8 java-stream

Convert InputStream into Stream<String> given a Charset中的内容一样,我想将InputStream is转换为Stream<String> stream。但这次不是将InputStream拆分为新行字符,而是将其拆分为相等长度的部分。因此,流的所有字符串都具有相同的长度(在流的最后一个元素上可能有例外,可能更短)。

2 个答案:

答案 0 :(得分:3)

我认为这不可能仅使用类库方法,因此您必须编写自己的逻辑,其遵循与BufferedReader.lines相同的模式:

  1. InputStreamReader - 首先创建一个InputStreamReader
  2. Iterator<String> - 实现一个自定义Iterator子类,可以根据需要将流拆分为多个部分。听起来您希望实现hasNext()next()来调用最多可读取N个字符的readPart()
  3. Spliterators.spliteratorUnknownSize - 将迭代器传递给此方法以创建Spliterator。
  4. StreamSupport.stream - 将Spliterator传递给此方法以创建流。
  5. 最终,类库没有用于从输入流中读取并转换为固定大小字符串的内置函数,因此您必须为#1 /#2编写这些内容。之后,转换为#3 /#4中的流并不算太糟糕,因为有类库方法可以提供帮助。

答案 1 :(得分:3)

没有直接的支持。您可以创建一个直接的工厂方法:

static Stream<String> strings(InputStream is, Charset cs, int size) {
    Reader r=new InputStreamReader(is, cs);
    CharBuffer cb=CharBuffer.allocate(size);
    return StreamSupport.stream(new Spliterators.AbstractSpliterator<String>(
        Long.MAX_VALUE, Spliterator.ORDERED|Spliterator.NONNULL) {
            public boolean tryAdvance(Consumer<? super String> action) {
                try { while(cb.hasRemaining() && r.read(cb)>0); }
                catch(IOException ex) { throw new UncheckedIOException(ex); }
                cb.flip();
                if(!cb.hasRemaining()) return false;
                action.accept(cb.toString());
                cb.clear();
                return true;
            }
        }, false).onClose(()->{
            try { r.close(); }catch(IOException ex) { throw new UncheckedIOException(ex); }
        });
}

可以像:

一样使用
try(Stream<String> chunks=strings(is, StandardCharsets.UTF_8, 100)) {
    // perform operation with chunks
}