如何从Java8个Streams获取Inputstream?
How to obtain Inputstream from Java 8 Streams?
我有一些数据来自不同的文件。格式如下:
Stream<String> linesModifiedAndAppendedFromVariousFiles=getLines();
但是,我需要将其提供给接受 InputStream 或 Reader 作为参数的库方法。
如何将此 Java 8 流输入 InputStream 或 Reader 类型?
P.S:这与将 java.util.streams.Stream 环绕在 InputStream 上无关。我正在寻找的是相反的方式。
A java.util.Stream
在概念上是一个潜在的无限的、不可逆的(比如,一旦你经过一个条目你就不能回到它)序列,它可能允许你并行处理它.至关重要的是,序列中的 'thingies' 可以是 ANYTHING。例如,您可以有一个 Color 对象流。
一个java.io.InputStream
在概念上是一个潜在的无限的、不可逆的、不可并行化的字节序列。
这两件事完全不一样。
但是,如果您有专门的字节流,则可以将其转换为输入流。您只是选择不使用 Stream 中固有的并行化选项,然后这两件事开始归结为同一件事。但是,如果您有任何不是字节的流,则必须提出 'mapping'.
假设您有一个字符串对象流。假设这是英文前 4 个数字的流(因此:Arrays.asList("one", "two", "three", "four").stream()
)。
您想如何将此字符串流映射到字节流?一种策略可能是使用 UTF-8 编码将字符串呈现为字节,并使用 0 字符作为分隔符。换句话说,您想要与这个假设相同的结果:new ByteArrayInputStream(new String("one[=14=]two[=14=]three[=14=]four").getBytes(StandardCharsets.UTF_8))
.
可以想象一个函数接收 Stream<Byte>
并将其转换为 InputStream。但是,Stream<Byte>
将是一个非常低效的概念。还可以想象一个函数,它接受 Stream<T>
以及一个将 T
映射到 byte[]
的映射函数,以及一个生成分隔符的分隔符常量(或生成值的函数)。对于上面的示例,类似于:
toInputStream(oneTwoThreeFour, str -> str.getBytes(StandardCharsets.UTF_8), "[=10=]");
据我所知,这在核心库和番石榴之类的地方都不存在。但是写它应该是微不足道的。可能是半页的代码。
您可以使用 PipedReader and PipedWriter 来做到这一点。
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);
读取字节流:
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;
};
}
我有一些数据来自不同的文件。格式如下:
Stream<String> linesModifiedAndAppendedFromVariousFiles=getLines();
但是,我需要将其提供给接受 InputStream 或 Reader 作为参数的库方法。
如何将此 Java 8 流输入 InputStream 或 Reader 类型?
P.S:这与将 java.util.streams.Stream 环绕在 InputStream 上无关。我正在寻找的是相反的方式。
A java.util.Stream
在概念上是一个潜在的无限的、不可逆的(比如,一旦你经过一个条目你就不能回到它)序列,它可能允许你并行处理它.至关重要的是,序列中的 'thingies' 可以是 ANYTHING。例如,您可以有一个 Color 对象流。
一个java.io.InputStream
在概念上是一个潜在的无限的、不可逆的、不可并行化的字节序列。
这两件事完全不一样。
但是,如果您有专门的字节流,则可以将其转换为输入流。您只是选择不使用 Stream 中固有的并行化选项,然后这两件事开始归结为同一件事。但是,如果您有任何不是字节的流,则必须提出 'mapping'.
假设您有一个字符串对象流。假设这是英文前 4 个数字的流(因此:Arrays.asList("one", "two", "three", "four").stream()
)。
您想如何将此字符串流映射到字节流?一种策略可能是使用 UTF-8 编码将字符串呈现为字节,并使用 0 字符作为分隔符。换句话说,您想要与这个假设相同的结果:new ByteArrayInputStream(new String("one[=14=]two[=14=]three[=14=]four").getBytes(StandardCharsets.UTF_8))
.
可以想象一个函数接收 Stream<Byte>
并将其转换为 InputStream。但是,Stream<Byte>
将是一个非常低效的概念。还可以想象一个函数,它接受 Stream<T>
以及一个将 T
映射到 byte[]
的映射函数,以及一个生成分隔符的分隔符常量(或生成值的函数)。对于上面的示例,类似于:
toInputStream(oneTwoThreeFour, str -> str.getBytes(StandardCharsets.UTF_8), "[=10=]");
据我所知,这在核心库和番石榴之类的地方都不存在。但是写它应该是微不足道的。可能是半页的代码。
您可以使用 PipedReader and PipedWriter 来做到这一点。
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);
读取字节流:
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;
};
}