【问题标题】:Compare data of each line from file1 to data from file 2比较文件 1 中每一行的数据与文件 2 中的数据
【发布时间】:2020-07-30 02:19:23
【问题描述】:

我有两个大约 150 mb 的大 txt 文件。我想从 file1 的每一行读取一些数据并扫描 file2 的所有行,直到找到匹配的数据。如果没有找到匹配的数据,我想将该行输出到另一个文件。

我希望程序使用尽可能少的内存。时间不是限制。

编辑1

我已经尝试了几个选项

Option1:我已经使用 BufferedReader、Scanner 和 apache commons FileUtils.lineIterator 读取了 file2。通过读取每一行将file2的数据加载到HashMap中。一次从file1中读取数据,并与HashMap中的数据进行比较。如果不匹配,则将该行写入文件3。

选项 2:使用上述三个读取器读取文件 1 中的每条记录的文件 2 n 次。每次读取后,我必须关闭文件并再次读取。我想知道最好的方法是什么。我还有其他选择吗

【问题讨论】:

  • 这是一个有趣的问题,但到目前为止您尝试过什么,通过自己的研究发现了什么?
  • 使用BufferedReader读取File的内容,然后以你想要的方式进行比较。
  • @Abs 太好了,您能否更新您的问题以向我们展示您的尝试,然后我们可以进一步帮助您解决问题。有很多方法可以实现这一点(Scanner、BufferedReader),但是通过查看您的尝试,我们可以提出更好的建议。
  • 如果你没问题,错误非常少,我想你可以使用选项 1,而不是在 hashmap 中逐行存储,你可以使用 md5 hash..
  • @aravind 好主意,您应该将其发布为答案。

标签: java performance java-8


【解决方案1】:

我必须对文件做出一些假设。 我将假设这些行很长,并且您希望两个文件中的行不同。

我会阅读文件 4 次(每个文件 2 次)。 当然,它的效率不如读取 2 次(每个文件 1 次),但读取 2 次意味着使用大量内存。

每个文件第一次读取的伪代码:

Map<MyComparableByteArray, Long> digestMap = new HashMap<>();
try (BufferedReader br = ...)
{
    long lineNr = 0;
    String line;
    while ((line = br.readLine()) != null)
    {
        digestMap.put(CreateDigest(line), lineNr);
    }
}

如果摘要不同/唯一,我知道该行不会出现在另一个文件中。 如果摘要相同,我们将需要检查行并实际比较它们以确保它们确实相同 - 这可能发生在第二次读取期间。

现在同样重要的是,我们需要注意我们选择的摘要。 如果我们选择一个简短的摘要(即 md-5),我们可能会遇到很多冲突,但这适用于具有短行的文件,我们需要单独处理冲突(即将地图转换为 map 结构。

如果我们选择一个长摘要(即 sha2-512),我们将不会遇到很多冲突(像我上面提到的那样处理它仍然更安全),但是我们将遇到无法节省尽可能多内存的问题,除非文件行很长。

所以一般的技术是:

  1. 读取每个文件并生成哈希。
  2. 比较哈希以标记需要比较的行。
  3. 再次读取每个文件并生成输出。重新检查此步骤中哈希发现的所有冲突。

顺便说一句,MyComparableByteArray 是一个 byte[] 的自定义包装器,以使其成为 HashMap 键(即通过实现 equals() 和 hashCode() 方法)。 byte[] 不能用作键,因为它不适用于 equals() 和 hashCode()。有两种处理方法:

  1. 我已经提到过自定义包装器 - 这将比替代方法更有效。
  2. 使用 base64 将其转换为字符串。这将使内存使用量比选项 1 差 2.5 倍左右,但不需要自定义代码。

【讨论】:

    猜你喜欢
    • 2023-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-26
    • 2015-05-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多