0

我有一个文件

base.txt
5071111111
5071111112
5071111113
5071111114
..... around 15 lakh numbers

和另一个文件

status.txt
5071111112,sended
5071111113,failed
..... 

实际情况是,我有包含用于发送消息的手机号码的基本文件和包含存储在 status.txt 中的每个号码的消息状态的其他文件。

现在我的任务是合并两个文件并保留普通文件

merged.txt
5071111111
5071111112,sended
5071111113,failed
5071111114
....... and so on

我尝试了通常的解决方案,从 status.txt 中获取一个数字,即“5071111112,已发送”并与 base.txt 进行比较,如果找不到数字,则复制 merge.txt 中的数字,如果找到数字,则复制更新后的内容merge.txt 中的编号。

现在,merged.txt 将作为我的基础文件。

此外,status.txt 文件会定期出现,因此比较和创建新的 merging.txt 文件以及删除以前的文件并重命名新文件的过程会不断进行。

我也尝试了 RandomAccessFile 类,但我面临与此处描述的问题类似的数据截断问题, 链接

我读了一些在 Stackoverflow 上发布的答案,但很多人都在建议我上面提到的方式。我们还有其他解决方案吗?

4

5 回答 5

1

有几种方法可以解决这个问题,它们不是 Java 特定的(这是人们一直在逃避的)。这些是 CS 问题

您需要做的是找到集合“A”与集合“B”的交集——在 Java 2 中,现成的类可以做到这一点(HashSet 和 TreeSet)。这些都由其等效的 Map 类型支持。

有两种方法可以解决这个问题:

1) 以二进制搜索树的形式对文件进行分块排序(这意味着对于任何排序的树,子树也被排序)。在这种情况下,您将使用您认为可以为较小排序处理的任何内存空间创建排序子树(通常,内存空间将是文件中条目数的某个模数)。您可以将中间排序结果写入临时文件。

2)使用布隆过滤器显着减少考虑元素的数量。创建超集的布隆过滤器(对于您的情况,它是没有状态代码的文件)。然后使用过滤器明确删除永远不会在另一个集合中的元素。

如果您没有明确的超集,您可以应用交叉过滤,在其中为集合“A”创建一组布隆位,并从“B”中删除任何肯定不包含在“A”中的内容,然后反转此过程.

你最终得到的是两个“可能”相交的小得多的集合。此时您可能只使用 setA.retainAll(setB) 来生成公共元素。

如果您的套装很笨重,您可以在下面应用 #1 或 #3 之前使用 #2

3)使用 cassandra 和一些 virts设置map-reduce 作业。您可以设置一些 EC2 实例或使用内部 virts。你的工作会更快完成。

于 2013-05-03T18:13:44.130 回答
0

如果文件不是特别大,您可以阅读文件并将数字放入地图中。

Map<String(Phonenumber), String(Status)>

然后您逐行阅读第二个文件并将状态放入地图中。

完成后,您遍历 Map 并将其写入合并文件。

for(Entry<String, String>e  : map.entrySet())
  write(e.getvalue());

但是,如果您可以将所有内容加载到内存中,这很容易做到,因此这取决于这些文件的实际大小。如果我们谈论的是千兆字节,那么它可能不起作用。

如果可以选择安装 即 cygwin 以便您可以使用 unix shell 命令,我会这样做(或者如果您可以将它们放在一个文件中):

sort -u base status > temporary

这样,您就可以保证每个数字都紧随其后。然后写一个小的java脚本来读取每一行。将数字保留在内存中,当有更多状态消息出现时,添加它们。当下一个数字与您将其写入合并文件之前不同时,这将是您的最终结果。

于 2013-05-03T16:55:20.690 回答
0

我将构建两个输入流并读取 base.txt 和 status.txt 的第一行并比较它们

环形:

- 如果数字相等(在 status.txt 中创建一个子字符串并将其与 base.txt 进行比较)从 base.txt 写入行并重新释放两行

- 如果它们不相等,则写下数字较小的那个并重新计算

阅读下一行

这只有在它们按数字排序时才有效(否则你应该先对它们进行排序)。

如果运行时间没有问题,您可以轻松实现冒泡排序并逐行执行;)

于 2013-05-03T16:57:59.203 回答
0

假设您的文件已经或可以进行排序,那么使用您所描述的两个光标将它们合并是最好的解决方案。

您也可以考虑使用数据库。

于 2013-05-03T17:06:14.323 回答
0

我只是在您的帖子的帮助下考虑并实施了一种解决方案并获得了预期的结果。只是想确认它是否是好的解决方案。

现在第一步,我正在对我的 base.txt 文件进行排序

在第二步中,我将包含大约 10,00,000 个数字的 base.txt 文件拆分为多个文件,每个文件中包含 1,00,000 个数字。(我在拆分文件时要记住,而不是完整的 10,00,000 个数字通过使用 HashMap 或其他东西在内存中,我可能会进入内存不足错误)。

现在在基本文件被拆分成块之后。我正在维护 1 个索引文件,用于跟踪拆分文件中存在的数字。

limit                 file-name
1-1,00,000            split0.txt
1,00,001-2,00,000     split1.txt

现在,我开始阅读 status.txt 文件,并从中选择一个我必须合并的数字,在索引文件的帮助下,我将知道我必须选择哪个文件进行更新。

现在,由于带有块的文件包含大约 1,00,000 个数字(例如 split4.txt ),我将其放入 hashMap 并更新正确的记录并将 hashMap 再次写入该文件。

通过使用此解决方案,我得到了预期的结果,只是想确认,这是正确的方法还是我遗漏了任何东西。

谢谢

于 2013-05-05T19:17:16.790 回答