gpt4 book ai didi

java - 按最大行拆分非常大的文本文件

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:25:23 25 4
gpt4 key购买 nike

我想将一个包含字符串的大文件拆分成一组新的(较小的)文件并尝试使用 nio2。

我不想将整个文件加载到内存中,所以我尝试使用 BufferedReader。

较小的文本文件应受文本行数的限制。

该解决方案有效,但我想问问是否有人知道使用 java 8(也许是带有 stream()-api 的 lamdas?)和 nio2 性能更好的解决方案:

public void splitTextFiles(Path bigFile, int maxRows) throws IOException{

int i = 1;
try(BufferedReader reader = Files.newBufferedReader(bigFile)){
String line = null;
int lineNum = 1;

Path splitFile = Paths.get(i + "split.txt");
BufferedWriter writer = Files.newBufferedWriter(splitFile, StandardOpenOption.CREATE);

while ((line = reader.readLine()) != null) {

if(lineNum > maxRows){
writer.close();
lineNum = 1;
i++;
splitFile = Paths.get(i + "split.txt");
writer = Files.newBufferedWriter(splitFile, StandardOpenOption.CREATE);
}

writer.append(line);
writer.newLine();
lineNum++;
}

writer.close();
}
}

最佳答案

注意直接使用 InputStreamReader的区别/OutputStreamWriter及其子类和Reader/Writer factory methods of Files .在前一种情况下,当没有给出明确的字符集时使用系统的默认编码,而后者总是默认为 UTF-8。因此,我强烈建议始终指定所需的字符集,即使它是 Charset.defaultCharset()StandardCharsets.UTF_8 来记录您的意图并避免在切换时出现意外创建 ReaderWriter 的各种方法。


如果你想在行边界处分割,没有办法绕过查看文件的内容。所以你不能优化它 like when merging .

如果您愿意牺牲可移植性,您可以尝试一些优化。如果您知道字符集编码将明确地将 '\n' 映射到 (byte)'\n' 就像大多数单字节编码以及 UTF-8 您可以扫描字节级别的换行符以获取拆分的文件位置,并避免从您的应用程序到 I/O 系统的任何数据传输。

public void splitTextFiles(Path bigFile, int maxRows) throws IOException {
MappedByteBuffer bb;
try(FileChannel in = FileChannel.open(bigFile, READ)) {
bb=in.map(FileChannel.MapMode.READ_ONLY, 0, in.size());
}
for(int start=0, pos=0, end=bb.remaining(), i=1, lineNum=1; pos<end; lineNum++) {
while(pos<end && bb.get(pos++)!='\n');
if(lineNum < maxRows && pos<end) continue;
Path splitFile = Paths.get(i++ + "split.txt");
// if you want to overwrite existing files use CREATE, TRUNCATE_EXISTING
try(FileChannel out = FileChannel.open(splitFile, CREATE_NEW, WRITE)) {
bb.position(start).limit(pos);
while(bb.hasRemaining()) out.write(bb);
bb.clear();
start=pos;
lineNum = 0;
}
}
}

缺点是它不适用于 UTF-16EBCDIC 之类的编码,并且与 BufferedReader.readLine() 不同,它不支持单独的 '\r' 作为旧 MacOS9 中使用的行终止符。

此外,它只支持小于2GB的文件;由于虚拟地址空间有限,该限制在 32 位 JVM 上可能更小。对于大于限制的文件,有必要遍历源文件的 block 并将它们一个接一个地映射

这些问题可以解决,但会增加此方法的复杂性。考虑到在我的机器上速度提高只有大约 15%(我没想到更多,因为 I/O 在这里占主导地位)并且当复杂性增加时速度会更小,我认为这不值得。


底线是对于此任务,Reader/Writer 方法就足够了,但您应该注意用于此任务的 Charset操作。

关于java - 按最大行拆分非常大的文本文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25553673/

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