Как я могу использовать InputStream для частей RandomAccessFile?

Я новичок в Java, и я написал парсер, который работает на RandomAccessFile (формат файла требует случайного позиционирования). Для тестирования JUnit я загружаю в синтаксический анализатор различные образцы входных файлов.

Теперь я подумал, что смогу написать более простые тесты JUnit после того, как изменю синтаксический анализатор на чтение из InputStream (который будет создан тестом JUnit).

Но чтобы иметь возможность выполнить вариант использования без тестирования, мне пришлось бы создать (или обновить) InputStream, чтобы прочитать, на что в настоящее время указывает RandomAccessFile. Возможно ли это? Конечно, решение должно быть эффективным и элегантным.


person U. Windl    schedule 22.05.2018    source источник
comment
Возможно, вам будет легче помочь, если вы покажете код.   -  person Andy Turner    schedule 22.05.2018
comment
@Энди Тернер: код для открытия RandomAcessFile, код для чтения из такого файла или (еще не существующий) код для чтения из InputStream? Или что именно вы ищете?   -  person U. Windl    schedule 22.05.2018
comment
Из stackoverflow.com /questions/9287664/ Я понимаю, что SeekableByteChannel с Channels.newInputStream() звучит как возможное решение, но без буферизации.   -  person U. Windl    schedule 22.05.2018
comment
Читая описание InputStream (BufferedInputStream), я задаюсь вопросом, будет ли проще всего реализовать новый класс, делегирующий RandomAccessFile, добавляя setPosition() (и аннулирующий буфер при изменении позиции в случае BufferedInputStream).   -  person U. Windl    schedule 22.05.2018


Ответы (1)


Поскольку ни у кого не было более умной идеи, вот что я сделал. К сожалению, очень ограниченный характер конструкторов и использование super(), а также отсутствие множественного наследования в Java делают реализацию более сложной и уродливой, чем необходимо. Также отсутствие защищенного invalidate() для буфера BufferedInputStream заставило меня задуматься, как это сделать (тест показал, что это работает):

package de.whatever.uw.utils;

import java.io.BufferedInputStream;

/**
 * @author U. Windl
 */
public class RandomAccessFileInputStream extends BufferedInputStream {

    private RandomAccessFile file;  // file to use

   /**
     * Constructor
     * @param fileName File to open for reading
     * @throws FileNotFoundException 
     */
    public RandomAccessFileInputStream(String fileName) throws FileNotFoundException {
        super(System.in);   // dummy to work around Java's inflexibility
        assert fileName != null;
        file = new RandomAccessFile(fileName, "r");
        FileChannel channel = file.getChannel();
        in = new BufferedInputStream(Channels.newInputStream(channel));
        assert file != null;
    }

    /**
     * Forbidden Constructor
     * @param in Input stream
     */
    private RandomAccessFileInputStream(InputStream in) {
        super(in);
    }

    /**
     * Forbidden Constructor
     * @param in
     * @param size
     */
    private RandomAccessFileInputStream(InputStream in, int size) {
        super(in, size);
    }

    /* (non-Javadoc)
     * @see java.io.BufferedInputStream#close()
     */
    public void close() throws IOException {
        super.close();
        file.close();
    }

    /**
     * @return Current offset in stream
     * @throws IOException
     */
    public long getFilePointer() throws IOException {
        return file.getFilePointer();
    }

    /**
     * @return
     * @throws IOException
     * @see java.io.RandomAccessFile#length()
     */
    public long length() throws IOException {
        return file.length();
    }

    /**
     * @param pos New stream position
     * @throws IOException
     */
    public void seek(long pos) throws IOException {
        file.seek(pos);
        pos = count = 0;    // invalidate stream buffer
    }

    // other methods are inherited without change (and I really use a very few of them actually)
}

(Я создал специальный тестовый файл размером около 8 КБ для проверки позиционирования и буферизации: после изменения позиции считываются правильные данные (отмена буфера, кажется, работает), и считывается больше запрошенного размера данных (т. е. буферизация также работает). ))

person U. Windl    schedule 23.05.2018
comment
Спасибо, как раз то, что мне было нужно сегодня! - person gregko; 19.04.2021