Java 如何表示空的InputStream
我正在减少Java 如何表示空的InputStream,java,java-stream,inputstream,Java,Java Stream,Inputstream,我正在减少InputStreams流,如下所示: InputStream total = input.collect( Collectors.reducing( empty, Item::getInputStream, (is1, is2) -> new SequenceInputStream(is1, is2))); 对于标识InputStream,我使用: InputStream empty = new ByteArrayIn
InputStreams
流,如下所示:
InputStream total = input.collect(
Collectors.reducing(
empty,
Item::getInputStream,
(is1, is2) -> new SequenceInputStream(is1, is2)));
对于标识InputStream
,我使用:
InputStream empty = new ByteArrayInputStream(new byte[0]);
这是可行的,但是有没有更好的方法来表示空的
InputStream
?因为InputStream
只有一个抽象方法
public abstract int read()抛出IOException
返回:数据的下一个字节,或
-1
(如果到达流的末尾)
通过一个实例创建一个空流是很容易的。
像这样:
InputStream empty = new InputStream() {
@Override
public int read() {
return -1; // end of stream
}
};
但不可否认,它比你的空
ByteArrayInputStream
更多的是代码,我会走另一条路
通过(is1,is2)->新的SequenceInputStream(is1,is2)
减少大量的InputStream
实例可能会创建一个深度不平衡的SequenceInputStream
实例树,这可能会变得非常低效
线性数据结构更合适:
InputStream total = new SequenceInputStream(
Collections.enumeration(input.map(Item::getInputStream).collect(Collectors.toList())));
这将创建单个SequenceInputStream
来处理所有收集的输入流。由于这在本质上也处理空列表情况,因此不再需要特殊的空InputStream
实现
但是当你看的时候,你会发现这个类并没有什么神奇之处,事实上,我们甚至可以通过不使用像
Vector
和Enumeration
这样的古老类来做得更好:
public class StreamInputStream extends InputStream {
final Spliterator<? extends InputStream> source;
final Consumer<InputStream> c = is -> in = Objects.requireNonNull(is);
InputStream in;
public StreamInputStream(Stream<? extends InputStream> sourceStream) {
(source = sourceStream.spliterator()).tryAdvance(c);
}
public StreamInputStream(InputStream first, InputStream second) {
this(Stream.of(first, second));
}
public int available() throws IOException {
return in == null? 0: in.available();
}
public int read() throws IOException {
if(in == null) return -1;
int b; do b = in.read(); while(b<0 && next());
return b;
}
public int read(byte b[], int off, int len) throws IOException {
if((off|len) < 0 || len > b.length - off) throw new IndexOutOfBoundsException();
if(in == null) return -1; else if(len == 0) return 0;
int n; do n = in.read(b, off, len); while(n<0 && next());
return n;
}
public void close() throws IOException {
closeCurrent();
}
private boolean next() throws IOException {
closeCurrent();
return source.tryAdvance(c);
}
private void closeCurrent() throws IOException {
if(in != null) try { in.close(); } finally { in = null; }
}
}
自Java 11以来,您可以使用静态方法: 返回不读取字节的新InputStream。返回的流最初是打开的。通过调用close()方法关闭流。对close()的后续调用无效
如果您的项目中有Apache
commons io
:
import org.apache.commons.io.IOUtils
IOUtils.toInputStream("")
以什么方式更好?使用空的
BAIS
,有什么不好?只是一个想法。。。您知道,您可以将输入流收集到一个列表中,然后只需执行SequenceInputStream(Collections.enumeration(yourCollectedList))
?@Kayaman相当小,但会创建一个额外的空字节数组。我最感兴趣的是,如果我错过了集合中的某些内容。emptyList()。仅供参考,您可以用SequenceInputStream::new
替换new SequenceInputStream(is1,is2)
。这很聪明(至少对我来说),1+哦,我需要尝试一下。。。我们使用的是第一种方法(正如我在评论中所说的),这看起来更圆滑,但接近于确认。。。这将影响我们的代码基础(再次!)非常值得注意的是,InputStream.nullInputStream()
不支持标记
,而不是newbytearrayinputstream(新字节[0])
。
import org.apache.commons.io.IOUtils
IOUtils.toInputStream("")