Как я могу использовать InputStream для частей RandomAccessFile? - PullRequest
0 голосов
/ 22 мая 2018

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

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

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

1 Ответ

0 голосов
/ 23 мая 2018

Поскольку никто не имел более умной идеи, вот что я сделал.К сожалению, очень ограниченная природа конструкторов и использование 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 КБ для проверки позиционирования и буферизации: после изменения позиции считываются правильные данные (кажется, что недействительный буфер работает), и больше, чем запрашивается размер данных (т.е. буферизация также работает).)

...