简体   繁体   English

如何从Java 8 Streams获取Inputstream?

[英]How to obtain Inputstream from Java 8 Streams?

I have some data streamed from different files.我有一些从不同文件流式传输的数据。 It is in the following format:它采用以下格式:

Stream<String> linesModifiedAndAppendedFromVariousFiles=getLines();

However, I need to feed this into an library method that accepts InputStream or Reader as a parameter.但是,我需要将其提供给接受 InputStream 或 Reader 作为参数的库方法。

How can I feed this Java 8 stream into an InputStream or a type of Reader?如何将此 Java 8 流提供给 InputStream 或某种类型的 Reader?

PS: this is not about wrapping java.util.streams.Stream around an InputStream. PS:这不是关于将 java.util.streams.Stream 包装在 InputStream 周围。 What I am looking for is the other way around.我正在寻找的是相反的方式。

A java.util.Stream is conceptually a potentially endless, non-reversing (as in, once you move on past an entry you cant go back to it) sequence, which may potentially allow you to process it in parallel. java.util.Stream在概念上是一个潜在的无限的、不可逆的(例如,一旦您移动到一个条目之后就无法返回)序列,这可能允许您并行处理它。 Crucially, the 'thingies' in the sequence can be ANYTHING at all.至关重要的是,序列中的“东西”可以是任何东西 For example, you can have a stream of Color objects.例如,您可以有一个 Color 对象流。

A java.io.InputStream is conceptually a potentially endless, non-reversing, non-parallellizable sequence of bytes. java.io.InputStream在概念上是一个潜在的无限的、不可逆的、不可并行化的字节序列。

These 2 things are just not the same.这两件事是不一样的。

However, if you have a Stream of bytes specifically, you could feasibly turn that into an input stream.但是,如果您有专门的字节流,则可以将其转换为输入流。 You simply elect not to use the parallellization option inherent in Stream, and then these 2 things start boiling down to the same thing.您只是选择不使用 Stream 中固有的并行化选项,然后这两件事开始归结为同一件事。 However, if you have a stream of anything that isn't a byte, you will have to come up with the 'mapping'.但是,如果您有任何不是字节的流,则必须提出“映射”。

Let's say you have a stream of string objects.假设您有一个字符串对象流。 Let's say this is a stream of the first 4 numbers in english (so: Arrays.asList("one", "two", "three", "four").stream() ).假设这是英文前 4 个数字的流(因此: Arrays.asList("one", "two", "three", "four").stream() )。

How do you want to map this stream-of-strings into a stream-of-bytes?你想如何将这个字符串流映射到字节流? One strategy could be to render the strings to bytes using UTF-8 encoding, and to use the 0 char as a separator.一种策略可能是使用 UTF-8 编码将字符串呈现为字节,并使用 0 字符作为分隔符。 In other words, that you want the same result as this hypothetical: new ByteArrayInputStream(new String("one\0two\0three\0four").getBytes(StandardCharsets.UTF_8)) .换句话说,您想要与这个假设相同的结果: new ByteArrayInputStream(new String("one\0two\0three\0four").getBytes(StandardCharsets.UTF_8))

One can imagine a function that takes in a Stream<Byte> and turns it into an InputStream.可以想象一个接受Stream<Byte>并将其转换为 InputStream 的函数。 However, a Stream<Byte> would be a very inefficient concept.但是, Stream<Byte>将是一个非常低效的概念。 One can also imagine a function that takes a Stream<T> along with a mapping function mapping T to byte[] , and a separator constant (or function that generates a value) that produces the separators.还可以想象一个函数,它采用Stream<T>以及将T映射到byte[]的映射函数,以及一个生成分隔符的分隔符常量(或生成值的函数)。 For the above example, something like:对于上面的示例,类似于:

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

as far as I know, this does not exist in the core libraries nor in places like guava.据我所知,这在核心库和番石榴之类的地方都不存在。 But writing it should be trivial enough.但是写它应该是微不足道的。 Maybe half a page's worth of code.也许半页的代码。

You can do this with PipedReader and PipedWriter .您可以使用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);

Reading stream of bytes:读取字节流:

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

Here are the methods to generate input stream下面是生成输入流的方法

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM