如何从Java 8 Streams获得Inputstream?

时间:2019-04-16 13:55:54

标签: java stream inputstream bufferedreader

我有一些来自不同文件的数据流。格式如下:

Stream<String> linesModifiedAndAppendedFromVariousFiles=getLines();

但是,我需要将其提供给接受InputStream或Reader作为参数的库方法。

如何将Java 8流馈送到InputStream或类型的Reader中?

P.S:这不是关于将java.util.streams.Stream封装在InputStream周围。我正在寻找的是相反的方式。

3 个答案:

答案 0 :(得分:2)

您可以使用PipedReaderPipedWriter来做到这一点。

PipedReader reader = new PipedReader();

Runnable feeder = new Runnable() {
    @Override
    public void run() {
        try (PipedWriter writer = new PipedWriter(reader)) {
            linesModifiedAndAppendedFromVariousFiles.forEachOrdered(line -> {
                try {
                    writer.write(line);
                    writer.write('\n');
                } catch (IOException e) {
                    throw new UncheckedIOException(e);
                }
            });
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
};
new Thread(feeder).start();

someLibraryMethod.consumeReader(reader);

答案 1 :(得分:1)

java.util.Stream从概念上讲可能是无止境的,不可逆的(例如,一旦经过一个条目,您将无法返回它),这可能会允许您并行处理它。至关重要的是,序列中的“东西”完全可以是任何东西。例如,您可以拥有一个Color对象流。

java.io.InputStream从概念上讲是潜在的无穷无尽,不可逆的字节序列。

这两件事根本不一样。

但是,如果您有专门的字节流,则可以将其转换为输入流。您只需选择不使用Stream固有的并行化选项,然后这两件事就会变成同一件事。但是,如果您拥有不小于字节的任何内容流,则必须提出“映射”。

假设您有一个字符串对象流。假设这是英文的前4个数字(例如:Arrays.asList("one", "two", "three", "four").stream())的流。

您如何将这个字符串流映射为字节流?一种策略是使用UTF-8编码将字符串呈现为字节,并使用0字符作为分隔符。换句话说,您想要与以下假设相同的结果:new ByteArrayInputStream(new String("one\0two\0three\0four").getBytes(StandardCharsets.UTF_8))

可以想象一个函数,它接受Stream<Byte>并将其转换为InputStream。但是,Stream<Byte>是一个非常低效的概念。人们还可以想象一个函数,它包含一个Stream<T>和一个将T映射到byte[]的映射函数,以及一个分隔符常量(或生成值的函数),该分隔符常量会产生分隔符。对于上面的示例,类似:

toInputStream(oneTwoThreeFour, str -> str.getBytes(StandardCharsets.UTF_8), "\0");
据我所知,

在核心库中也不存在,在诸如番石榴之类的地方也不存在。但是编写它应该很简单。也许只有一页代码的价值。

答案 2 :(得分:0)

读取字节流:

    PipedInputStream inputStream = new PipedInputStream();
    Thread infinitInputStreamSupplier = infinitInputStreamSupplierThread(inputStream);
    infinitInputStreamSupplier.start();
    //consume input stream here...
    infinitInputStreamSupplier.interrupt();

以下是生成输入流的方法

private Thread infinitInputStreamSupplierThread(final PipedInputStream inputStream) {
        return new Thread(() -> {
            try (PipedOutputStream outputStream = new PipedOutputStream(inputStream)) {
                Stream<byte[]> infiniteStream = Stream.generate(randomByteSupplier());
                infiniteStream.forEachOrdered(bytes -> {
                    try {
                        outputStream.write(bytes);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
    }

    private Supplier<byte[]> randomByteSupplier() {
        return () -> {
            byte[] bytes = new byte[100];
            new Random().nextBytes(bytes);

            return bytes;
        };
    }