2013-05-03 66 views
0

修改大文件I有一个文件阅读比较和用java

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,sended”,并比较base.txt 和如果未找到号码,则将该号码复制到merged.txt中,如果找到号码,则将该号码的更新后的内容复制到merged.txt中。

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

此外,status.txt文件定期进入,所以比较和创建新的merging.txt文件以及删除以前的文件并重新命名新文件的过程依此类推。

我也尝试过的RandomAccessFile类,但我面对数据截断问题的相似之处在于这里所描述的问题, link

我读张贴#2,但许多人都建议我上面提到的方式几个答案。 我们有其他解决方案吗?

+0

数字是否保证在文件中排序? (因为他们中的例子) – FDinoff 2013-05-03 16:49:02

+3

对于我们这些南亚之外,一个“十万”根据http://en.wikipedia.org/wiki/Lakh是十万(100,000)。 – rgettman 2013-05-03 16:50:40

+0

不,它不会被排序,因为号码的状态不会发生。 base.txt文件,我们可以对它进行排序,但status.txt文件来以任意顺序,也有像行大数据“5071111112,提交PLAYER1,player2,失败,正在重试...” – Jayesh 2013-05-03 16:53:30

回答

1

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

你需要做的是找到集合'A'与集合'B'的交集 - 在Java 2就绪类中可以做到这一点(HashSet和TreeSet)。这些都由其等效的地图类型支持。

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

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

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

如果你没有一个清晰的超级集合,你可以应用交叉过滤,在你为集合'A'创建一组盛放位并从'B'中删除任何肯定不包含在'A'中的任何然后扭转这个过程。

你最终得到的是两个“可能”相交的小得多的集合。在这一点上,你可以使用setA.retainAll(setB)来产生公共元素。

如果你的套只是笨拙,你可以使用#2#应用1或以下

3#3)之前设置一个地图,减少与卡桑德拉和一些virts工作。您可以设置一些EC2实例或使用内部版本。你的工作会快得多。

+0

嘿基督教,我不知道布隆过滤器,我会尝试使用它。关于您的第三种解决方案,我们之前已经使用hadoop,但由于维护,我们希望摆脱它,因为在这种情况下数据不会太高以至于无法使用hadoop。 – Jayesh 2013-05-04 03:18:24

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脚本读取每一行。记住内存中的号码以及更多状态消息到来时,添加它们。当下一个数字与之前不一样时,将它写入合并文件,这将是您的最终结果。

+0

我无法做到这一点,因为它会用完内存。我已经尝试过,并使用jconsole,我也可以看到。 – Jayesh 2013-05-03 16:57:11

+0

您是否尝试使用mx选项增加内存? – Devolus 2013-05-03 16:57:43

+0

实际上通过增加MX的选择,我可以尝试,但我不想去的内存解决方案,我的文件将是很大的。 – Jayesh 2013-05-03 16:59:32

0

我将构建两个输入流并读取base.txt的第一行和状态。TXT 并加以比较

循环:

- 如果这些数字是相等的(请在status.txt中的子字符串,并将其与base.txt比较) 写从base.txt和realease行两条线

- 如果它们不相等写一个具有较低numhber和realese它

读取下一行(S)

这只会工作,如果他们是由n个有序成员(否则你应该先排序)。

如果运行时间是没有问题的,你可以很容易地实现冒泡排序,并通过线做线;)

0

假设您的文件,也可以,排序,用两个光标像你描述的是将它们合并最佳方案。

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

+0

嘿ykaganovich,在这种方法每次我有时间来创建新的文件,然后删除旧的和重命名新的。是RandomAccessFile类可以帮助我在这种情况下? – Jayesh 2013-05-03 17:08:31

+0

我的直觉告诉我,创建一个新文件更具有高性能。 – ykaganovich 2013-05-03 20:32:27

0

我只是想和实施一个解决方案与您的帖子的帮助,并获得所需的结果。 只是想确认是否是好的解决方案。

现在第一步,我整理我的base.txt文件

在第二个步骤,我分裂我的base.txt文件,其中包含大约10,00,000号到许多文件,包括1,00,000号在每个文件中(我在考虑拆分文件,而不是通过使用HashMap或其他内容获取完整的10,00,000个数字),我可能会进入内存不足错误。

现在基础文件被拆分成块。我维护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到该文件。

我用这个解决方案得到期望的结果,只是想确认,它是正确的做法还是我缺少什么。

谢谢