Java:从具有缓冲输入的随机访问文件中读取字符串
问题内容:
之前我从未接触过Java IO API,现在真的很沮丧。我发现很难相信这是多么的奇怪和复杂,以及完成一项简单的任务有多困难。
我的任务:我有2个位置(开始字节,结束字节)pos1
和pos2
。我需要读取这两个字节之间的行(包括开始的一个,不包括结束的一个),并将它们用作UTF8字符串对象。
例如,在大多数脚本语言中,这将是非常简单的1-2-3-liner(在Ruby中,但对于Python,Perl等基本上相同):
f = File.open("file.txt").seek(pos1)
while f.pos < pos2 {
s = f.readline
# do something with "s" here
}
Java IO API很快就使您陷入困境;)实际上,我看到了两种\n
从常规本地文件中读取行(以结尾)的方式:
- RandomAccessFile具有
getFilePointer()
和seek(long pos)
,但它的readLine()读取非UTF8字符串(甚至不是字节数组),但是具有破损编码的非常奇怪的字符串,并且没有缓冲(这可能意味着每个read*()
调用都将转换为单个不拖延的OSread()
= >相当慢)。 - BufferedReader有一个很棒的
readLine()
方法,它甚至可以使用进行某些搜索skip(long n)
,但是它无法确定已读取的偶数字节,没有提及文件中的当前位置。
我尝试使用类似:
FileInputStream fis = new FileInputStream(fileName);
FileChannel fc = fis.getChannel();
BufferedReader br = new BufferedReader(
new InputStreamReader(
fis,
CHARSET_UTF8
)
);
…然后fc.position()
用于获取当前文件的读取位置并fc.position(newPosition)
设置一个,但是在我的情况下似乎不起作用:看起来它返回由BufferedReader完成的缓冲区预填充的位置,或类似的东西-
这些计数器似乎以16K的增量取整。
我是否真的必须自己实现所有功能,即一个文件读取接口,该接口将:
- 请允许我获取/设置文件位置
- 缓冲文件读取操作
- 允许读取UTF8字符串(或至少允许类似“将所有内容读取到下一个
\n
”之类的操作)
有没有比自己全部实施更快的方法?我在监督什么吗?
问题答案:
import org.apache.commons.io.input.BoundedInputStream
FileInputStream file = new FileInputStream(filename);
file.skip(pos1);
BufferedReader br = new BufferedReader(
new InputStreamReader(new BoundedInputStream(file,pos2-pos1))
);
如果您不关心pos2
,那么您就不需要Apache Commons IO。