gpt4 book ai didi

java - 读取文本文件时跳过最后 x 行

转载 作者:搜寻专家 更新时间:2023-11-01 01:11:09 27 4
gpt4 key购买 nike

我逐行从大文件中读取文本数据。
但我只需要阅读 n-x 行(不要阅读最后 x 行)。

如何在不读取整个文件超过 1 次的情况下做到这一点?
(我读取行并立即处理它,所以我不能返回)

最佳答案

在这篇文章中,我将为您提供两种完全不同的方法来解决您的问题,并且根据您的用例,其中一种解决方案会比另一种更适合。

备选 #1

这种方法虽然非常复杂,但内存效率高,如果您要跳过很多内容,建议使用这种方法,因为在处理过程中您一次只会在内存中存储一​​行。

本文中它的实现可能不是 super 优化的,但它背后的理论很清楚。

您将从向后阅读文件开始,搜索 N 个换行符。当您成功找到文件中您想稍后停止处理的位置时,您将跳回到文件的开头。

备选 #2

这个方法很容易理解,也很直接。在执行期间,您将在内存中存储 N 行,其中 N 是您最后想要跳过的行数。

行将存储在 FIFO 容器中(先进先出)。您会将最后一个读取行附加到您的 FIFO,然后删除并处理第一个条目。这样,您将始终处理距文件末尾至少 N 个条目的行。



选择#1

这听起来可能很奇怪,但绝对可行,而且我建议您采用这种方式;从向后阅读文件开始。

  1. 查找文件末尾
  2. 读取(并丢弃)字节(朝向文件的开头)直到找到 SKIP_N换行符
  3. 保存这个位置
  4. 定位到文件开头
  5. 阅读(和处理)行,直到你回到你存储的位置

示例代码:

下面的代码将去掉最后一个 42来自 /tmp/sample_file 的行并使用本文前面描述的方法打印其余部分。

import java.io.RandomAccessFile;
import java.io.File;

import java.lang.Math;

public class Example {
protected static final int SKIP_N = 42;

public static void main (String[] args)
throws Exception
{
File fileHandle = new File ("/tmp/sample_file");
RandomAccessFile rafHandle = new RandomAccessFile (fileHandle, "r");
String s1 = new String ();

long currentOffset = 0;
long endOffset = findEndOffset (SKIP_N, rafHandle);

rafHandle.seek (0);

while ((s1 = rafHandle.readLine ()) != null) {
; currentOffset += s1.length () + 1; // (s1 + "\n").length
if (currentOffset >= endOffset)
break;

System.out.println (s1);
}
}

protected static long findEndOffset (int skipNLines, RandomAccessFile rafHandle)
throws Exception
{
long currentOffset = rafHandle.length ();
long endOffset = 0;
int foundLines = 0;

byte [] buffer = new byte[
1024 > rafHandle.length () ? (int) rafHandle.length () : 1024
];

while (foundLines < skipNLines && currentOffset != 0) {
currentOffset = Math.max (currentOffset - buffer.length, 0);

rafHandle.seek (currentOffset);
rafHandle.readFully (buffer);

for (int i = buffer.length - 1; i > -1; --i) {
if (buffer[i] == '\n') {
++foundLines;

if (foundLines == skipNLines)
endOffset = currentOffset + i - 1; // we want the end to be BEFORE the newline
}
}
}

return endOffset;
}
}


备选#2

  1. 逐行读取文件
  2. 在每一个成功读取的行上,插入你的 LinkedList<String> 后面的行
  3. 如果您的 LinkedList<String>包含的行多于您希望跳过的行数,删除第一个条目并处理它
  4. 重复直到没有更多行可读

示例代码

import java.io.InputStreamReader;
import java.io.FileInputStream;
import java.io.DataInputStream;
import java.io.BufferedReader;

import java.util.LinkedList;

public class Example {
protected static final int SKIP_N = 42;

public static void main (String[] args)
throws Exception
{
String line;

LinkedList<String> lli = new LinkedList<String> ();

FileInputStream fis = new FileInputStream ("/tmp/sample_file");
DataInputStream dis = new DataInputStream (fis);
InputStreamReader isr = new InputStreamReader (dis);
BufferedReader bre = new BufferedReader (isr);

while ((line = bre.readLine ()) != null) {
lli.addLast (line);

if (lli.size () > SKIP_N) {
System.out.println (lli.removeFirst ());
}
}

dis.close ();
}
}

关于java - 读取文本文件时跳过最后 x 行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8494455/

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