我有一个文件
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上发布了几个答案,但很多人都在暗示我上面提到的方式。 我们还有其他任何解决方案。
答案 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
之前使用#23)使用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写入该文件。
我通过使用此解决方案获得了预期的结果,只是想确认,这是正确的方法还是我遗漏了任何东西。
由于