Why cant a RandomAccessFile be casted to Inputstream?
Asked Answered
R

4

8

I get compilation error when I do this cast:

RandomAccessFile raf = new RandomAccessFile(...)
InputStream is = (InputStream)raf;

RandomAccessFile is supposed to subclass InputStream although not directly.

From docs:

RandomAccessFile implements DataInput which inturn DataInputstream & InputStream

Why is this invalid?

Also appreciate your input on what would be the right way to use the RandomAccessFile as InputStream?

I am thinking of wrapper approach.

Roebuck answered 15/2, 2012 at 3:58 Comment(3)
The point of a RandomAccessFile is that it isn't a stream (it's not sequential). Why would you want to change that? Just make a FileInputStream.Sarsen
And what do you mean by your "file cache is not disturbed with RAF..."? What is the ultimate goal of this code? You will need to tell the details if you want help solving a problem. Consider checking out this link How To Ask Questions The Smart Way which contains great tips on how to make forum questions more easily answered.Rosewater
@Sarsen well that is ignorant... There are numerous cases. For instance, if you use IOUtils.copyLarge from apache commons that uses InputStream, so you seek your RandomAccessFile and then create wrapper InputStream, but again there is no reason why couldn't RandomAccessFile extend InputStream...People
D
17

RandomAccessFile extends Object, and does not extend InputStream.

If you want get an InputStream from a RandomAccessFile I think implementing a wrapper class is your simplest bet. Luckily the only abstract method of InputStream is read().

RandomAccessFile implements DataInput which inturn DataInputstream & InputStream

DataInputStream is a subclass of InputStream, which also happens to implement DataInput. The inheritance and interface implementation tree looks like this:

           InputStream      DataInput
               \              /   \
                \            /     \
                 \          /       \
                DataInputStream   RandomAccessFile

You could use a DataInputStream anywhere where you could use an InputStream or a DataInput. You could use a RandomAccessFile anywhere where you could use a DataInput.

But you can't go up and then down in the inheritance hierarchy like this using casts. In particular, casting a class to a subclass (or an interface to an implementation) will raise a ClassCastException unless the object happens to be an instance of the child class.

Even though two classes happen to extend Object that doesn't mean they are interchangeable.

Drawshave answered 15/2, 2012 at 4:0 Comment(2)
sverre, thanks for answering my dumb question. I didnt read the hierarchy correctly.Roebuck
This is easily achievable using the Channels utility class... // STEP 1: Create random access file read-only RandomAccessFile raf = new RandomAccessFile("/text.txt", "r"); // STEP 2: Use Channels to convert to InputStream InputStream is = Channels.newInputStream(raf.getChannel()); (answered separately)Livingston
L
55

This is easily achievable using the Channels utility class...

// STEP 1:  Create random access file read-only
RandomAccessFile raf = new RandomAccessFile("/text.txt", "r");

// STEP 2:  Use Channels to convert to InputStream
InputStream is = Channels.newInputStream(raf.getChannel());
Livingston answered 29/1, 2015 at 19:14 Comment(2)
@dpg I feel like it will close the stream after read completes, which is not the case if you read from the file DataInput interface.Altair
Does that InputStream have any kind of buffering, and if so, is that buffer invalidated/refreshed after a position change in the RandomAccessFile?Broadwater
D
17

RandomAccessFile extends Object, and does not extend InputStream.

If you want get an InputStream from a RandomAccessFile I think implementing a wrapper class is your simplest bet. Luckily the only abstract method of InputStream is read().

RandomAccessFile implements DataInput which inturn DataInputstream & InputStream

DataInputStream is a subclass of InputStream, which also happens to implement DataInput. The inheritance and interface implementation tree looks like this:

           InputStream      DataInput
               \              /   \
                \            /     \
                 \          /       \
                DataInputStream   RandomAccessFile

You could use a DataInputStream anywhere where you could use an InputStream or a DataInput. You could use a RandomAccessFile anywhere where you could use a DataInput.

But you can't go up and then down in the inheritance hierarchy like this using casts. In particular, casting a class to a subclass (or an interface to an implementation) will raise a ClassCastException unless the object happens to be an instance of the child class.

Even though two classes happen to extend Object that doesn't mean they are interchangeable.

Drawshave answered 15/2, 2012 at 4:0 Comment(2)
sverre, thanks for answering my dumb question. I didnt read the hierarchy correctly.Roebuck
This is easily achievable using the Channels utility class... // STEP 1: Create random access file read-only RandomAccessFile raf = new RandomAccessFile("/text.txt", "r"); // STEP 2: Use Channels to convert to InputStream InputStream is = Channels.newInputStream(raf.getChannel()); (answered separately)Livingston
D
6

To build on @robert-christian’s answer, the main reason to use RandomAccessFile to begin with is to seek to some position, rather than skipping bytes from a FileInputStream. But then why bother with pre-NIO APIs at all?

try (FileChannel ch = FileChannel.open(Paths.get(…), StandardOpenOption.READ)) {
    InputStream is = Channels.newInputStream(ch.position(…));
    // …
}
Decani answered 29/9, 2016 at 18:51 Comment(0)
R
4

RandomAccessFile is supposed to extends InputStream although not directly.

No it isn't. See the Javadoc.

From docs:

RandomAccessFile implements DataInput which in turn DataInputstream & InputStream.

That's not 'from the docs' at all. You made it up. What you've written doesn't even make sense. DataInput is an interface. DataInputStream and InputStream are classes. Interfaces don't implement, or extend, classes.

What the Javadoc actuallys says is that RandomAccessFile extends java.lang.Object and implements Closeable, DataInput, DataOutput.

Reflex answered 15/2, 2012 at 4:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.