gpt4 book ai didi

Java - 根据偏移量从随机访问文件中获取行

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:14:51 27 4
gpt4 key购买 nike

我有一个非常大的 (11GB) .json 文件(是的,谁认为 是个好主意?)我需要对其进行采样(读取 k 随机行) .

我对 Java 文件 IO 不是很了解,但我当然找到了这篇文章: How to get a random line of a text file in Java?

我放弃了已接受的答案,因为显然 方式 读取 11GB 文件的每一行只是从中选择一个(或者更确切地说是 k)太慢了大约 10 万行。

幸运的是,那里发布了第二个建议,我认为它可能对我更有用:

Use RandomAccessFile to seek to a random byte position in the file.

Seek left and right to the next line terminator. Let L the line between them.

With probability (MIN_LINE_LENGTH / L.length) return L. Otherwise, start over at step 1.

到目前为止一切顺利,但我想知道“让 L 成为它们之间的界线”。

我会做这样的事情(未经测试):

RandomAccessFile raf = ...
long pos = ...
String line = getLine(raf,pos);
...

在哪里

private String getLine(RandomAccessFile raf, long start) throws IOException{
long pos = (start % 2 == 0) ? start : start -1;

if(pos == 0) return raf.readLine();

do{
pos -= 2;
raf.seek(pos);
}while(pos > 0 && raf.readChar() != '\n');

pos = (pos <= 0) ? 0 : pos + 2;
raf.seek(pos);
return raf.readLine();
}

然后使用 line.length() 进行操作,这样就无需显式地寻找行的右端。

那么为什么要“向左和向右寻找下一行终止符”呢?有没有更方便的方法从这两个偏移量得到直线?

最佳答案

看起来这会做大致相同的事情 - raf.readLine() 正在寻找下一行终止符;它只是为你做的。


需要注意的一件事是 RandomAccessFile.readLine()不支持从文件中读取 unicode 字符串:

Each byte is converted into a character by taking the byte's value for the lower eight bits of the character and setting the high eight bits of the character to zero. This method does not, therefore, support the full Unicode character set.

错误阅读演示:

import java.io.*;
import java.nio.charset.StandardCharsets;

class Demo {
public static void main(String[] args) throws IOException {
try (FileOutputStream fos = new FileOutputStream("output.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
BufferedWriter writer = new BufferedWriter(osw)) {
writer.write("ⵉⵎⴰⵣⵉⵖⵏ");
}

try (RandomAccessFile raf = new RandomAccessFile("output.txt", "r")) {
System.out.println(raf.readLine());
}
}
}

输出:

âµâµâ´°âµ£âµâµâµ

但是 output.txt 确实包含正确的数据:

$ cat output.txt
ⵉⵎⴰⵣⵉⵖⵏ

因此,您可能希望自己进行查找,或者将 raf.readLine() 的结果显式转换为正确的字符集:

String line = new String(
raf.readLine().getBytes(StandardCharsets.ISO_8859_1),
StandardCharsets.UTF_8);

关于Java - 根据偏移量从随机访问文件中获取行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37481340/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com