7

java.io.InputStream.skip() says "Throws: IOException - if the stream does not support seek, or if some other I/O error occurs."

how do i know which filestream supports seek?

when google i find Seekable, but i can see that simple FileInputStream, ByteArrayInputStream ... also supports skip(), i mean does not give IOException; they does not extend Seekable.

Rakesh Malik
  • 607
  • 1
  • 6
  • 27

4 Answers4

6

The only way to know for sure is to read the javadocs for any particular stream you're interested in. The inheritance hierarchy is quite bad there, but it's an old class.

Edit: I just read the javadoc, and while it seems that InputStream itself does implement it (with a naive read/discard implementation), it says

"Subclasses are encouraged to provide a more efficient implementation of this method. For instance, the implementation may depend on the ability to seek."

Now instead of throwing an IOException if seeking isn't supported, subclasses could always use the default implementation. However, most likely due to backwards compatibility, this artifact of weird design has been left in.

Kayaman
  • 72,141
  • 5
  • 83
  • 121
  • 2
    Unfortunately the JavaDocs do not help at all. Most InputStream subclasses that come with the JRE just repeat what is said in InputStream. So the only way is to call the method and observe the result. Basically you should treat that method as an optional performance improvement over reading and discarding N bytes. – Torben Jan 15 '14 at 11:45
  • ...so does that mean there may have been some class may be inside/outside java.io / user-defined which may not support seek, and should throw IOException from skip() – Rakesh Malik Jan 15 '14 at 12:13
  • @rakeshmalik91 The seek is only an implementation suggestion (and a stupid one at that). If a stream doesn't support seek, it can always use other ways to skip bytes. This class definition is basically broken, since it makes assumptions and suggestions about subclasses that it shouldn't make. – Kayaman Jan 15 '14 at 12:15
5

You can move FileInputStream position with FileInputStream.getChannel.position(long). Skip is for streams, it is different from positioning, you cannot go back with it, it's for random access devices (HDD)

Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
3

InputStream is by definition not seekable. You can only skip forward, not backward in the stream (the only exception is rewinding the stream using reset(), works only on streams that support mark).

As for the skip() method, skipping is always possible, in fact the InputStream class already implements it generically by simply reading and discarding bytes. A particular InputStream subclass may implement it differently (more efficient for the specific type).

The throws comment "IOException - if the stream does not support seek, or if some other I/O error occurs." is misleading in that it implies that there may be streams that categorically do not allow to skip bytes (which makes no sense, as skipping is semantically the same as read+discard).

Durandal
  • 19,919
  • 4
  • 36
  • 70
  • Therefore it's a bit weird, that `org.apache.parquet:parquet-common` contains an abstract class `SeekableInputStream` – Tom Feiner Jun 23 '20 at 13:44
0

You can do a check over the type and decide otherwise for an exception ...

if !(in instanceof Seekable) { throw new IllegalArgumentException("not an instance of Seekable");

Mário de Sá Vera
  • 380
  • 1
  • 4
  • 12