仅将两个文本大文件与 Java 中的 URL 与外部存储器进行比较?
Posted
技术标签:
【中文标题】仅将两个文本大文件与 Java 中的 URL 与外部存储器进行比较?【英文标题】:Comparing two text large files with URLs in Java with external memory only? 【发布时间】:2018-12-03 17:39:57 【问题描述】:我有以下场景:
url文本文件A url文本文件B每个文件的大小约为 4Gb。
我需要计算:
A 中所有不在 B 中的 url B中所有不在A中的url我在网上找到的所有 Java-diff 示例都将整个列表加载到内存中(使用 Map 或使用 MMap 解决方案)。我的系统没有交换空间,而且没有外部内存就无法做到这一点。
有没有人知道这个问题的解决方案?
这个项目可以在不占用大量内存的情况下进行大型文件排序https://github.com/lemire/externalsortinginjava
我正在寻找类似的东西,但用于生成差异。我将首先尝试使用该项目作为基线来实现这一点。
【问题讨论】:
BufferedReader
?它们是文件中的许多“url”还是许多文本和一些url? => 将所有 URL 加载到内存中是一种解决方案吗?
嗨。不幸的是,没有。我已经尝试过了,但我的云虚拟机太小,无法处理内存解决方案或任何内存映射。它只需要是外部存储器
从你描述的方式来看,你必须做大量的传球。
我上面提到的java项目中的外部排序能够以几秒钟的方式对这些文件进行排序。所以我认为一旦我提出算法,它就不会太可怕了。
每个文本文件中的所有 URL 是否都是唯一的?如果不是,每个文件中唯一 URL 的大小是多少?
【参考方案1】:
如果系统有足够的存储空间,您可以通过 DB 执行此操作。例如:
创建一个 H2 或 sqlite DB(数据存储在磁盘上,分配尽可能多的 系统负担得起的缓存) 在表 A 和 B 中加载文本文件(在 'url' 列上创建索引)
select url from A where URL not in (select distinct url from B)
select url from B where URL not in (select distinct url from A)
【讨论】:
我可以试试。 查询只是一个例子,看看执行计划是否可以优化查询 在不完全杀死机器的情况下甚至无法将数据加载到表中。 它是哪个数据库(H2 还是 sqlite?) 正在使用 h2 的 csvload。很坏。可以试试sqlite【参考方案2】:这是我提出的解决方案的要点:https://gist.github.com/nddipiazza/16cb2a0d23ee60a07121893c26065de4
import com.google.common.collect.Sets;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
public class DiffTextFilesUtil
static public int CHUNK_SIZE = 100000;
static public class DiffResult
public Set<String> addedVals = new HashSet<>();
public Set<String> removedVals = new HashSet<>();
/**
* Gets diff result of two sorted files with each other.
* @param lhs left hand file - sort this using com.google.code.externalsortinginjava:externalsortinginjava:0.2.5
* @param rhs right hand file - sort this using com.google.code.externalsortinginjava:externalsortinginjava:0.2.5
* @return DiffResult.addedVals were added from lhs to rhs. DiffResult.removedVals were removed from lhs to rhs.
* @throws IOException
*/
public static DiffResult diff(File lhs, File rhs) throws IOException
DiffResult diffResult = new DiffResult();
LineIterator lhsIter = FileUtils.lineIterator(lhs);
LineIterator rhsIter = FileUtils.lineIterator(rhs);
String lhsTop = null;
String rhsTop = null;
while (lhsIter.hasNext())
int ct = CHUNK_SIZE;
Set<String> setLhs = Sets.newHashSet();
Set<String> setRhs = Sets.newHashSet();
while (lhsIter.hasNext() && --ct > 0)
lhsTop = lhsIter.nextLine();
setLhs.add(lhsTop);
while (rhsIter.hasNext())
if (rhsTop != null && rhsTop.compareTo(lhsTop) > 0)
break;
else if (rhsTop != null && rhsTop.compareTo(lhsTop) == 0)
setRhs.add(rhsTop);
rhsTop = null;
break;
else if (rhsTop != null)
setRhs.add(rhsTop);
rhsTop = rhsIter.next();
if (rhsTop != null)
setRhs.add(rhsTop);
Sets.difference(setLhs, setRhs).copyInto(diffResult.removedVals);
Sets.difference(setRhs, setLhs).copyInto(diffResult.addedVals);
return diffResult;
【讨论】:
以上是关于仅将两个文本大文件与 Java 中的 URL 与外部存储器进行比较?的主要内容,如果未能解决你的问题,请参考以下文章