【发布时间】:2010-11-29 15:19:38
【问题描述】:
我以前从未接触过 Java IO API,现在我真的很沮丧。我很难相信它是多么的奇怪和复杂,完成一项简单的任务是多么困难。
我的任务:我有 2 个位置(起始字节,结束字节),pos1 和 pos2。我需要读取这两个字节之间的行(包括开始一个,不包括结束一个)并将它们用作 UTF8 String 对象。
例如,在大多数脚本语言中,它会是一个非常简单的 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 字符串(甚至不是字节数组),但非常奇怪的字符串编码损坏,并且它没有缓冲(这可能意味着每个 @ 987654330@ 调用将被转换为单个操作系统read()=> 相当慢)。 -
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”之类的操作)
有没有比自己实现更快的方法?我在监督什么吗?
【问题讨论】:
-
RandomAccessFile用于二进制数据。尽管它可以使用writeUTF/readUTF存储和检索UTF-8 字符串,但正如您所发现的,它的readLine(以及一般DataInput接口的readLine)在UTF-8 上不起作用。 -
是否允许使用 openJDK 7(测试版)或 Apache Commons IO 等 3rd 方库?
-
@Martijn:无论如何,请发布您的 OpenJDK 7 和 Apache Commons IO 解决方案。我很好奇,可能其他人也是。
-
@Martijn Verburg:我不能使用 JDK 7,但欢迎任何第三方库。请回答,很有趣:)
-
@Ken Bloom - 我尝试了 Java 7 版本,但它仍然非常冗长,并且在运行时使用最新的 openJDK 构建实际上失败了 :(。唯一的优点是您可以使用多个线程从同一个文件并行读取/写入。无论如何我已经发布了。我承认还没有查找公共文件 I/O 的东西,我假设他们有一个比 JDK 1.5/1.6 更简单的 API ,我接下来看看
标签: java nio bufferedreader fileinputstream random-access