阅读使用java比较和修改大文件

时间:2013-05-03 16:47:18

标签: java file-io

我有一个文件

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进行比较 如果未找到数字,则复制merged.txt中的数字,如果找到数字,则复制更新的数字 merged.txt中该数字的内容。

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

此外,status.txt文件定期进入,因此比较和创建新的merging.txt文件并删除上一个文件并重命名新文件的过程会继续进行。

我也尝试过RandomAccessFile类,但我面临的数据截断问题类似于此处描述的问题, link

我在Stackoverflow上发布了几个答案,但很多人都在暗示我上面提到的方式。 我们还有其他任何解决方案。

5 个答案:

答案 0 :(得分:1)

有几种方法可以解决这个问题,而且它们并不是Java特有的(这是人们所不知道的)。 这些是CS问题

你需要做的是找到集合' A'用套装' B' - 在Java 2中,就绪类可以做到这一点(HashSet和TreeSet)。这些都由它们的等效Map类型支持。

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

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

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

如果你没有明确的超级套装,你可以应用交叉过滤,在那里你可以为套装创建一组花开的比特,A'并删除任何来自' B'这肯定不包含在' A'然后改变这个过程。

你最终得到的是2个极小的套装,可能是'相交。在这一点上,您可以使用setA.retainAll(setB)来生成公共元素。

如果您的套装只是笨拙,您可以在应用#1或#3

之前使用#2

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

答案 1 :(得分:0)

如果文件不是很大,你可以读取文件并将数字放在地图中。

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

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

完成后,您将迭代Map并将其写入合并文件。

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

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

如果它是一个安装ie cygwin的选项,所以你可以使用unix shell命令我会这样做(或者你可以在一个文件中将它们一起排序):

sort -u base status > temporary
通过这种方式,您可以确保每个号码都在彼此之后。 然后写一个小的java脚本读取每一行。加密内存中的数字,当有更多状态消息到来时,添加它们。当下一个数字与您将其写入合并文件之前不同时,这将是您的最终结果。

答案 2 :(得分:0)

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

循环:

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

- 如果它们不相等,则用较低的numhber写一个并将其重新定位

阅读下一行

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

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

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

我只是想到并在帖子的帮助下实现了一个解决方案,并获得了理想的结果。 只是想确认它是否是一个好的解决方案。

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

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

现在将基本文件拆分为块。我正在维护一个索引文件,用于跟踪拆分文件中存在的数字。

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写入该文件。

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

由于