我如何知道哪个文件流支持在 Java 中查找

Posted

技术标签:

【中文标题】我如何知道哪个文件流支持在 Java 中查找【英文标题】:how do i know which filestream supports seek in Java 【发布时间】:2014-02-03 20:40:58 【问题描述】:

java.io.InputStream.skip() 说“抛出: IOException - 如果流不支持查找,或者发生其他一些 I/O 错误。"

我如何知道哪个文件流支持搜索?

当 google 我发现 Seekable,但我可以看到简单的 FileInputStream、ByteArrayInputStream ... 也支持 skip(),我的意思是不给 IOException;它们不会扩展 Seekable。

【问题讨论】:

seek() 是抽象的,因此您必须查看子类并查看它们的 javadoc。 InputStream 没有 seek() 由于 InputStream 有一个默认的 skip() 实现,它只调用 read() 我会假设所有 InputStream 都支持这个方法,除非你知道。 【参考方案1】:

唯一确定的方法是阅读您感兴趣的任何特定流的 javadocs。那里的继承层次结构非常糟糕,但它是一个旧类。

编辑: 我刚刚阅读了 javadoc,虽然看起来 InputStream 本身 确实 实现了它(使用幼稚的读取/丢弃实现),但它说

"鼓励子类提供更高效的实现 这种方法。例如,实现可能取决于 寻找的能力。”

现在,如果不支持搜索,而不是抛出 IOException,子类可以始终使用默认实现。然而,很可能是由于向后兼容,这个奇怪的设计工件被留下了。

【讨论】:

不幸的是,JavaDocs 根本没有帮助。 JRE 附带的大多数 InputStream 子类只是重复 InputStream 中所说的内容。所以唯一的方法就是调用方法并观察结果。基本上,您应该将该方法视为相对于读取和丢弃 N 个字节的可选性能改进。 ...这是否意味着可能有一些类可能在 java.io 内部/外部 / 用户定义的可能不支持查找,并且应该从 skip() 抛出 IOException @rakeshmalik91 搜索只是一个实现建议(而且是一个愚蠢的建议)。如果流不支持查找,它总是可以使用其他方式跳过字节。这个类定义基本上被破坏了,因为它对子类做出了不应该做出的假设和建议。【参考方案2】:

您可以使用FileInputStream.getChannel.position(long) 移动FileInputStream 的位置。 Skip是针对流的,和定位不同,不能带回去,是针对随机存取设备(HDD)的

【讨论】:

对不起,我没听懂 你的意思是你不明白?其中哪一部分令人困惑? 我可以在 FileInputStream 中使用 skip() 跳过字节,如果我不想返回,我不需要“FileInputStream.getChannel.position(long)” 是的,我认为它们会产生相同的效果【参考方案3】:

InputStream 根据定义不可搜索。您只能在流中向前跳,不能向后跳(唯一的例外是使用 reset() 倒带流,仅适用于支持标记的流)。

对于skip()方法,跳过总是可能的,实际上InputStream类已经通过简单地读取和丢弃字节来实现它。特定的 InputStream 子类可能会以不同的方式实现它(对特定类型更有效)。

抛出注释“IOException - 如果流不支持查找,或者发生其他一些 I/O 错误。”具有误导性,因为它暗示可能存在绝对不允许跳过字节的流(这是没有意义的,因为跳过在语义上与读取+丢弃相同)。

【讨论】:

因此有点奇怪,org.apache.parquet:parquet-common 包含一个抽象类SeekableInputStream【参考方案4】:

您可以检查类型并决定是否有异常...

如果!(在Seekable的实例中) throw new IllegalArgumentException("不是 Seekable 的实例");

【讨论】:

以上是关于我如何知道哪个文件流支持在 Java 中查找的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 SQL 文件流 win32 API 并支持 WCF 流

java io流对文件的增删改查

java非常好用的读取文件的流的代码

如何在java-8中查找流类型[重复]

文件的流操作和speex

Java文件 ---流