您需要使用简单的预读逻辑.
x首先读取行并将它们放入缓冲区.然后,您可以一次重复读取一行,将其添加到缓冲区的末尾,并处理缓冲区中的第一行.到达时EOF,x缓冲区中有未处理的行.
更新:我注意到有关问题的评论和我自己的答案,所以只是为了澄清:我的建议在n未知的情况下有效.x当然应该知道.您需要做的就是创建一个简单的缓冲区,然后用x行填充缓冲区,然后开始处理.
关于缓冲区的实现,只要我们讨论Java的内置集合,只LinkedList需要一个简单的东西即可.因为你将为放入其中的每一行拉出缓冲区中的一行,所以ArrayList对数组索引的不断移位不会很好.一般来说,数组支持的缓冲区必须是循环的,以避免性能不佳.
在这篇文章中,我将为您提供两种完全不同的方法来解决您的问题,根据您的使用情况,其中一种解决方案比另一种更适合.
备选方案#1
这种方法虽然非常复杂,但内存效率非常高,如果您要跳过大量内容,建议使用此方法,因为在处理过程中,您只会在内存中一次存储一行.
在这篇文章中实现它可能不是超级优化,但它背后的理论很清楚.
您将从向后读取文件开始,搜索N个换行符.当您成功找到文件中的某个位置后,您希望稍后停止处理,您将跳回文件的开头.
备选方案#2
这种方法易于理解,非常简单.在执行期间,您将在内存中存储N行,其中N是您最后要跳过的行数.
这些行将存储在FIFO容器中(先进先出).您将最后一条读取行附加到FIFO,然后删除并处理第一个条目.这样,您将始终处理距离文件末尾至少N个条目的行.
这可能听起来很奇怪,但它绝对可行,而且我建议你这样做的方式; 首先向后阅读文件.
SKIP_N换行符下面的代码将删除最后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;
}
}
Run Code Online (Sandbox Code Playgroud)
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 ();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2432 次 |
| 最近记录: |