Почему файл RandomAccessFile не может быть приведен к Inputstream? - PullRequest
4 голосов
/ 15 февраля 2012

Я получаю ошибку компиляции при выполнении этого приведения:

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

RandomAccessFile должен быть подклассом InputStream, хотя не напрямую.

Из документов:

RandomAccessFile реализует DataInput, который вступает DataInputstream & InputStream

Почему это недействительно?

Также оцените ваш вклад в то, как правильно использовать RandomAccessFile как InputStream?

Я думаю о подходе обертки.

Ответы [ 4 ]

43 голосов
/ 29 января 2015

Этого легко достичь, используя служебный класс Channels ...

// 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());
16 голосов
/ 15 февраля 2012

RandomAccessFile расширяется Object, а не расширяется InputStream.

Если вы хотите получить InputStream от RandomAccessFile, я думаю, что реализация класса-обертки - ваша самая простая ставка. К счастью, единственный абстрактный метод InputStream - это read().

RandomAccessFile реализует DataInput, который включает DataInputstream & InputStream

DataInputStream - это подкласс InputStream, который также реализует DataInput. Дерево наследования и реализации интерфейса выглядит так:

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

Вы можете использовать DataInputStream везде, где вы можете использовать InputStream или DataInput. Вы можете использовать RandomAccessFile везде, где вы можете использовать DataInput.

Но вы не можете идти вверх и вниз по иерархии наследования, как это, используя приведение типов. В частности, приведение класса к подклассу (или интерфейсу к реализации) вызовет ClassCastException, если только объект не является экземпляром дочернего класса.

Даже если два класса расширяются Object, это не значит, что они взаимозаменяемы.

4 голосов
/ 15 февраля 2012

Предполагается, что RandomAccessFile расширяет InputStream, но не напрямую.

Нет, это не так.См. Javadoc.

Из документов:

RandomAccessFile реализует DataInput, что в свою очередь DataInputstream & InputStream.

Это не«из документов» вообще.Вы сделали это.То, что вы написали, даже не имеет смысла.DataInput это интерфейс.DataInputStream и InputStream являются классами.Интерфейсы не реализуют и не расширяют классы.

На самом деле Javadoc говорит, что RandomAccessFile расширяет java.lang.Object и реализует Closeable, DataInput, DataOutput.

3 голосов
/ 29 сентября 2016

Если исходить из ответа @ robert-christian, основной причиной использования RandomAccessFile для начала является seek до некоторой позиции, а не skip пинг байтов из FileInputStream. Но тогда зачем вообще использовать API до NIO?

try (FileChannel ch = FileChannel.open(Paths.get(…), StandardOpenOption.READ)) {
    InputStream is = Channels.newInputStream(ch.position(…));
    // …
}
...