比较两个文本文件的最快方法是什么,不将移动的行计算为不同
我有两个文件非常大,每个文件50000行。 我需要比较这两个文件并确定更改。 但是,如果一条线存在于不同位置,则不应该显示为不同。
例如,考虑一下
文件A.txt
xxxxx yyyyy zzzzz
文件B.txt
zzzzz xxxx yyyyy
所以如果这是文件的内容。 我的代码应该输出为xxxx(或xxxx和xxxxx)。
当然,最简单的方法是将文件的每一行存储在一个
List
并与其他人比较
List.
但这似乎需要花费很多时间。 我也尝试在java中使用DiffUtils。 但它不会将不同行号中的行识别为相同。 那么还有其他算法可以帮助我吗?
可能使用Set
是最简单的方法:
Set set1 = new HashSet (FileUtils.readLines(file1)); Set set2 = new HashSet (FileUtils.readLines(file2)); Set similars = new HashSet (set1); similars.retainAll(set2); set1.removeAll(similars); //now set1 contains distinct lines in file1 set2.removeAll(similars); //now set2 contains distinct lines in file2 System.out.println(set1); //prints distinct lines in file1; System.out.println(set2); //prints distinct lines in file2
通常,HashSet是最好的解决方案,但是当我们处理字符串时,有两种可能的解决方案:
-
将一个文件保存为HashSet并尝试在其中查找其他文件的行。
-
将一个文件保存为Trie并尝试在其中查找其他文件的行
在这篇文章中,您可以找到HashSets和Tries之间的比较如何在Hash Table和Trie(前缀树)之间进行选择?
您需要跟踪相同记录可能在文件中出现多次的情况。 例如,如果记录在文件A中出现两次而在文件B中出现一次,则需要将其记录为额外记录。
由于我们必须跟踪发生的次数,您需要以下之一:
- 一个Multiset
- 从记录到整数的映射,例如Map
使用Multiset,您可以添加和删除记录,它将跟踪记录添加的次数(Set不会这样做 – 它拒绝添加已经存在的记录)。 使用Map方法,您必须做一些工作,以便整数跟踪出现的次数。 让我们考虑一下这种方法(MultiSet更简单)。
使用地图,当我们谈论“添加”记录时,您会查看地图中是否有该字符串的条目。 如果有,请将值替换为该键的值+ 1。 如果没有,请创建值为1的条目。当我们谈论“删除条目”时,查找该键的条目。 如果找到它,请将值替换为值-1。 如果将值减小为0,请删除该条目。
- 为每个文件创建一个Map。
- 读取其中一个文件的记录
- 检查另一个Map中是否存在该记录。
- 如果它存在于另一个Map中,则删除该条目(参见上面的含义)
- 如果它不存在,请将其添加到此文件的Map(参见上文)
- 重复直到结束,交替文件。
两张地图的内容将为您提供该文件中出现的记录,而不是另一张。
我们继续这样做,而不是预先构建地图,可以降低内存使用率,但可能不会对性能产生很大影响。
您可以先尝试解析第一个文件,将所有行存储在HashMap中 ,然后检查是否存在第二个文件的每一行的映射。
不过,这仍然是O(n)。
只需使用与BufferedReader的字节比较。 这将是比较两个文件的最快方法。 从一个文件中读取一个字节块,并将其与另一个文件的字节块进行比较。 首先检查文件长度是否相同。
或者只使用FileUtils.contentEquals(file1, file2);
来自org.apache.commons.io.FileUtils
。
您可以使用FileUtils.contentEquals(file1,file2)
它将比较2个文件的内容。
在此处查找更多信息