如何将RandomStream用于RandomAccessFile的部分?

时间:2018-05-22 07:46:17

标签: java inputstream randomaccessfile

我是Java的新手,我编写了一个适用于RandomAccessFile的解析器(文件格式需要随机定位)。对于JUnit测试,我将不同的样本输入文件提供给解析器。

现在我认为在将解析器更改为从InputStream读取之后(可以通过JUnit测试创建),我可以编写更简单的JUnit测试。

但是为了能够执行非测试用例,我必须创建(或更新)InputStream来读取RandomAccessFile当前指向的位置。 这可能吗?当然,解决方案应该既高效又优雅。

1 个答案:

答案 0 :(得分:0)

由于没有人有更聪明的想法,这就是我所做的。遗憾的是,构造函数的非常有限的性质和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)
}

(我创建了一个大约8kB大小的特殊测试文件来测试定位和缓冲:更改位置后读取正确的数据(缓冲区似乎无效),并且读取的数据大小超过了所需的数据(即缓冲也有效。)