Java 如何比较大型文本文件?

Java 如何比较大型文本文件?,java,file,comparison,Java,File,Comparison,关于你对我的“技巧”的看法,我有一个一般性的问题 有两个文本文件(file_1和file_2)需要相互比较。两者都非常庞大(3-4G字节,从30000000到45000000行)。 我的想法是将文件1的几行(尽可能多)读入内存,然后将它们与文件2的所有行进行比较。如果存在匹配项,则应将两个文件中匹配的行写入新文件。然后继续下一个1000行的file_1,并将其与file_2的所有行进行比较,直到我完全阅读了file_1 但这听起来真的,真的很费时,对我来说很复杂。 你能想出其他方法来比较这两个文

关于你对我的“技巧”的看法,我有一个一般性的问题

有两个文本文件(
file_1
file_2
)需要相互比较。两者都非常庞大(3-4G字节,从30000000到45000000行)。 我的想法是将
文件1
的几行(尽可能多)读入内存,然后将它们与
文件2的所有行进行比较。如果存在匹配项,则应将两个文件中匹配的行写入新文件。然后继续下一个1000行的
file_1
,并将其与
file_2
的所有行进行比较,直到我完全阅读了
file_1

但这听起来真的,真的很费时,对我来说很复杂。 你能想出其他方法来比较这两个文件吗

你认为比较需要多长时间? 对于我的节目来说,时间没有那么重要。我没有处理如此巨大文件的经验,因此我不知道这可能需要多长时间。不过不应该超过一天但我担心我的技术可能会花很长时间

我突然想到另一个问题:你会在记忆中读多少行?尽可能多?在实际尝试之前,有没有办法确定可能的行数? 我想读尽可能多的书(因为我认为读得更快),但我经常会耗尽内存

提前谢谢

编辑 我想我得多解释一下我的问题

目的不是为了查看这两个文件是否完全相同(它们不是)。 每个文件中都有一些行具有相同的“特征”。 下面是一个例子:
文件_1
看起来有点像这样:

mat1 1000 2000 TEXT      //this means the range is from 1000 - 2000
mat1 2040 2050 TEXT
mat3 10000 10010 TEXT
mat2 20 500 TEXT
mat3 10009 TEXT
mat3 200 TEXT
mat1 999 TEXT
final List<String> lines = new ArrayList<>();
try{
    final List<String> block = new ArrayList<>(BLOCK_SIZE);
    for(int i=0;i<BLOCK_SIZE;i++){
       final String line = ...;//read line from file
       block.add(line);
    }
    lines.addAll(block); 
}catch(OutOfMemory ooe){
    //break
}
文件_2
如下所示:

mat1 1000 2000 TEXT      //this means the range is from 1000 - 2000
mat1 2040 2050 TEXT
mat3 10000 10010 TEXT
mat2 20 500 TEXT
mat3 10009 TEXT
mat3 200 TEXT
mat1 999 TEXT
final List<String> lines = new ArrayList<>();
try{
    final List<String> block = new ArrayList<>(BLOCK_SIZE);
    for(int i=0;i<BLOCK_SIZE;i++){
       final String line = ...;//read line from file
       block.add(line);
    }
    lines.addAll(block); 
}catch(OutOfMemory ooe){
    //break
}
TEXT
指我不感兴趣的字符和数字,
mat
可以从
mat1-mat50
开始,并且没有顺序;也可以有1000x
mat2
(但下一列中的数字不同)。我需要以一种方式找到拟合线:matX在两条比较线中都相同,
文件2
中提到的数字符合
文件1
中提到的范围。 因此,在我的示例中,我会找到一个匹配项:
file_1
的第3行和
file_2
的第1行(因为两者都是mat3,10009在10000和10010之间)。 我希望这能让你明白

所以我的问题是:你将如何搜索匹配的行

是的,我使用Java作为我的编程语言

编辑 我现在先把大文件分开,这样就不会出现内存不足的问题。我还认为比较(许多)较小的文件要比比较这两个大文件快。之后,我可以用上面提到的方法比较它们。这可能不是完美的方法,但我仍在学习;-)
尽管如此,你所有的方法都对我很有帮助,谢谢你的回复

有一个折衷办法:如果您读取了一大块文件,您可以保存光盘,但您可能已经读取了不需要的信息,因为更改是在第一行遇到的


您可能应该使用不同的数据块大小运行一些实验[基准测试],以找出在一般情况下,什么是最适合读取的数据块。

尽量避免内存消耗,并使其消耗磁盘。
我的意思是将每个文件分成可加载大小的部分并进行比较,这可能需要一些额外的时间,但会让您安全地处理内存限制

我从来没有处理过这么大的文件,但这是我的想法,应该行得通

你可以查一查。使用SHA-1散列

导入以下内容

import java.io.FileInputStream;
import java.security.MessageDigest;
一旦你的文本文件等已经加载,让它循环通过每一行,并在最后打印出散列。下面的示例链接将更深入

StringBuffer myBuffer = new StringBuffer("");
//For each line loop through
    for (int i = 0; i < mdbytes.length; i++) {
        myBuffer.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
    }
System.out.println("Computed Hash = " + sb.toString());
StringBuffer myBuffer=新的StringBuffer(“”);
//对于每条线路,循环通过
对于(int i=0;i

简单地分别读取每个文件,如果进程结束时每个文件的哈希值相同,则两个文件相同。如果没有,那就有问题了

然后,如果您得到一个不同的值,您可以执行非常耗时的逐行检查

总的来说,一行一行地阅读似乎要花很长时间。如果你想找出每个个体的差异,我会这么做。但我认为散列会更快地看到它们是否相同


不知道这是一个多么好的答案-但请看一下这一页:-它总结了一些不同的算法。Hunt-McIlroy算法可能是更好的实现。在该页面上还有一个指向GNU diff的java实现的链接。然而,我认为用C/C++实现并编译成本机代码会快得多。如果你被java所困扰,你可能会想JNI。

< P>在一个理想的世界里,你可以在Fiele2的每一行中读取内存(可能是使用一个快速查找对象,比如代码< HasSET//Cuth>,根据你的需要),然后一次读取文件_1中的每一行,并将其与保存文件_2中的行的数据结构进行比较

然而,正如你所说,你的内存不足,我认为分而治之的策略是最好的。您可以使用与我上面提到的相同的方法,但是从文件_2中读取一半(或三分之一,四分之一…取决于您可以使用的内存量)行并存储它们,然后比较文件_1中的所有行。然后将下半个/第三个/第四个/任何内容读入内存(替换旧行),并再次浏览文件_1。这意味着您必须再次查看文件1,但您必须处理内存限制。