如何将 InputStream 用于 RandomAccessFile 的一部分?
How can I use an InputStream for parts of a RandomAccessFile?
我是 Java 的新手,我编写了一个适用于 RandomAccessFile
的解析器(文件格式需要随机定位)。对于 JUnit 测试,我将不同的示例输入文件提供给解析器。
现在我认为在将解析器更改为从 InputStream
中读取(这将由 JUnit 测试创建)后,我可以编写更简单的 JUnit 测试。
但是为了能够执行非测试用例,我必须创建(或更新)一个 InputStream
来读取 RandomAccessFile
当前指向的位置。 这可能吗?当然,解决方案应该兼顾高效和优雅。
没有比这更聪明的主意了,这就是我所做的。不幸的是,构造函数的非常有限的性质和 super()
的使用以及 Java 中缺少多重继承使得实现比必要的更难和更丑陋。 BufferedInputStream
的缓冲区缺少受保护的 invalidate()
让我猜测如何去做(测试表明它有效):
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 大小的特殊测试文件来测试定位和缓冲:位置更改后读取正确的数据(使缓冲区无效似乎有效),并且读取的数据超过请求的大小(即缓冲也有效。)
我是 Java 的新手,我编写了一个适用于 RandomAccessFile
的解析器(文件格式需要随机定位)。对于 JUnit 测试,我将不同的示例输入文件提供给解析器。
现在我认为在将解析器更改为从 InputStream
中读取(这将由 JUnit 测试创建)后,我可以编写更简单的 JUnit 测试。
但是为了能够执行非测试用例,我必须创建(或更新)一个 InputStream
来读取 RandomAccessFile
当前指向的位置。 这可能吗?当然,解决方案应该兼顾高效和优雅。
没有比这更聪明的主意了,这就是我所做的。不幸的是,构造函数的非常有限的性质和 super()
的使用以及 Java 中缺少多重继承使得实现比必要的更难和更丑陋。 BufferedInputStream
的缓冲区缺少受保护的 invalidate()
让我猜测如何去做(测试表明它有效):
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 大小的特殊测试文件来测试定位和缓冲:位置更改后读取正确的数据(使缓冲区无效似乎有效),并且读取的数据超过请求的大小(即缓冲也有效。)