在这篇文章中,我将为您提供两种完全不同的方法来解决您的问题,并且根据您的用例,其中一种解决方案会比另一种更适合。
备选方案#1
此方法虽然相当复杂,但内存效率很高,如果您要跳过大量内容,建议您使用此方法,因为您在处理过程中一次只会在内存中存储一行。
本文中的实现可能没有超级优化,但其背后的理论很清楚。
您将从向后读取文件开始,搜索 N 个换行符。当您成功找到文件中您希望稍后停止处理的位置时,您将跳回到文件的开头。
备选方案#2
这种方法很容易理解,而且非常直接。在执行期间,您将在内存中存储 N 行,其中 N 是您最后要跳过的行数。
这些行将存储在一个 FIFO 容器中(先进先出)。您将最后读取的行附加到您的 FIFO,然后删除并处理第一个条目。这样,您将始终处理距文件末尾至少 N 个条目的行。
备选方案#1
这听起来可能很奇怪,但绝对可行,而且我建议您这样做;首先向后阅读文件。
- 查找文件末尾
- 读取(并丢弃)字节(朝向文件开头),直到找到
SKIP_N 换行符
- 保存此职位
- 寻找到文件的开头
- 阅读(和处理)行,直到您到达您存储的位置
示例代码:
下面的代码将从/tmp/sample_file 中删除最后的42 行,并使用本文前面描述的方法打印其余部分。
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
- 逐行读取文件
- 在每一个成功读取的行中,插入
LinkedList<String> 后面的行
- 如果您的
LinkedList<String> 包含的行数多于您想跳过的行数,请删除第一个条目并进行处理
- 重复直到没有更多的行要读取
示例代码
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 ();
}
}