Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 性能改进:如何在30分钟内仅读取100000个文件的最后10行_Java_Performance_File Io_Collections - Fatal编程技术网

Java 性能改进:如何在30分钟内仅读取100000个文件的最后10行

Java 性能改进:如何在30分钟内仅读取100000个文件的最后10行,java,performance,file-io,collections,Java,Performance,File Io,Collections,我有一个疑问,关于我应该使用哪一个集合。我们已经讨论了很多,但需要更多的投入 我有一个源系统,每30分钟就有100000个交易文件进入我的应用程序。每个文件都有许多行代码(比如1000行)。我的应用程序应该只存储和处理最后10行交易详细信息 如果我使用缓冲区读取器逐行读取文件内容,那么我必须继续在某个集合中添加每一行的详细信息,最后,当我到达最后一行时,以某种方式删除所有内容,只保留最后10行。因此,即使我不需要全部,也要收集所有1000行,这是一个性能问题。是否有任何收集或方法来改进此功能。您

我有一个疑问,关于我应该使用哪一个集合。我们已经讨论了很多,但需要更多的投入

我有一个源系统,每30分钟就有100000个交易文件进入我的应用程序。每个文件都有许多行代码(比如1000行)。我的应用程序应该只存储和处理最后10行交易详细信息

如果我使用缓冲区读取器逐行读取文件内容,那么我必须继续在某个集合中添加每一行的详细信息,最后,当我到达最后一行时,以某种方式删除所有内容,只保留最后10行。因此,即使我不需要全部,也要收集所有1000行,这是一个性能问题。是否有任何收集或方法来改进此功能。

您可以使用:

CircularFifoBuffer是一个具有固定大小的先进先出缓冲区,如果已满,它将替换最早的元素

仅在内存中保留最后10行的用法:

CircularFifoBuffer buffer = new CircularFifoBuffer(10);
// read lines and add them to the buffer
BufferedReader in = ...
String[] buffer = new String[10];
int bufferStartIndex = 0;
for (String line; (line = in.readLine()) != null;) {
    buffer[bufferStartIndex++ % buffer.length] = line;
}

在读取行的末尾,缓冲区只包含最后10行。

您可以轻松地创建一个丢弃队列,只保留最后10行。
LinkedList
将是这样一个实现的良好开端。关于这个话题


这并不能解决读取整个文件的问题,但是绕开它意味着更多的编码。您需要一个
RandomAccessFile
并从末尾搜索第10个换行符。此解决方案的适用性取决于文件的大小。

您可以使用大小为10的字符串数组,并且始终只存储最后10行:

CircularFifoBuffer buffer = new CircularFifoBuffer(10);
// read lines and add them to the buffer
BufferedReader in = ...
String[] buffer = new String[10];
int bufferStartIndex = 0;
for (String line; (line = in.readLine()) != null;) {
    buffer[bufferStartIndex++ % buffer.length] = line;
}

在for循环的末尾,
bufferStartIndex
将指向文件最后10行中的第一行。但是,如果文件包含的行数少于10行,则应将
bufferStartIndex
重置为0。

使用RandomAccessFile,并尝试读取更大的缓冲区。 我做了一个带有行长度提示的
tail
函数来进行猜测。请注意,文件是否以换行结束,或者可能会对结果产生影响。此外,还可以改进代码(两个块大小的幂等)

File textFile=新文件(“…”);
字符串[]行=尾部(文本文件,“UTF-8”,10160);
System.out.println(“#行:“+行.长度”);
用于(字符串行:行){
系统输出打印项次(行);
}
字符串[]尾部(文件textFile、字符串字符集、int行、int行长度提示)
抛出IOException{
如果(lineLengthHint<80){
lineLengthHint=80;
}
RandomAccessFile in=新的RandomAccessFile(文本文件,“r”);
试一试{
long fileSize=in.length();
int bytesCount=行*行长度提示;
//循环分配一个足够大的字节数组。
对于(;;){
if(文件大小<字节数){
字节数=(int)文件大小;
}
字节[]字节=新字节[字节计数];
in.seek(文件大小-字节数);
in.readfull(字节);
int startIndex=bytes.length;//最后一个'\n'的位置。
int lineEndsFromStart=0;
布尔字节数=真;
while(lineEndsFromStart-1<行){
int pos=startIndex-1;
而(pos>=0&&bytes[pos]!='\n'){
--pos;
}
startIndex=pos;//-1就可以了。
++lineEndsFromStart;
如果(位置<0){
bytescontfulfuld=false;
打破
}
}
if(字节数足够| | fileSize==字节数){
字符串文本=新字符串(字节,起始索引+1,
bytes.length-(startIndex+1),字符集);
返回文本。拆分(“\r?\n”);
}
//不充分:
//lineLengthHint+=10;//平均线长度较大。
bytesCount+=lineLengthHint*4;//请尝试使用更多。
}
}最后{
in.close();
}
}
导入java.io.BufferedReader;
导入java.io.FileInputStream;
导入java.io.IOException;
导入java.io.InputStreamReader;
导入java.util.LinkedList;
导入java.util.Queue;
公开课考试{
私有静态队列底部=新建LinkedList();
私有静态整数计数=0;
公共静态void main(字符串[]args)引发IOException{
func(3);
}
//函数获取计数,底部n行
私有静态void func(int n)引发IOException{
FileInputStream fstream=新的FileInputStream(“abc.txt”);
BufferedReader br=新的BufferedReader(新的InputStreamReader(fstream));
弦斯特林;
//逐行读取文件
而((strLine=br.readLine())!=null){
计数++;

如果(countLakh不是一个全球公认的单位。为了吸引更广泛的受众,你可能需要使用10万或10.1百万。为什么你认为你需要在一个集合中存储所有行?你也可以只存储最后读取的10行,每次读取一行时,丢弃最旧的一行。我在一次中断中看到最大96k行,最小23k行ans 30分钟。这个数字有所不同。这个数字可能也会增加。我们可以假设96k1。打开文件。2。寻找文件的结尾。3。收集向后移动的行,直到有10行。4。处理。5。冲洗,重复。不需要存储大量你不关心的数据。@Crowder:在java中,我们如何从文件的结尾开始读取文件?我会看一遍gh CircularFifoBuffer详细说明。这是否意味着,随着我们不断添加新元素,它将继续覆盖早期元素,最后我们将剩下10个元素?是的。最后缓冲区只包含最后10行。我们可以避免读取文件中的所有行吗?我的意思是直接访问最后10行。正如其他人所建议的,yo你可以。从最后开始,然后倒退。但这需要更多