比较大csv文件的最佳方法?

时间:2014-03-24 08:56:37

标签: java comparator

我必须做一个应用程序,比较一些非常大的csv文件,每个文件有40,000条记录。我已经完成了一个正常运行的应用程序,但它花费了大量时间进行比较,因为这两个文件可能会被混乱或有不同的记录 - 因为我必须迭代(40000 ^ 2)* 2次。

这是我的代码:

  if (nomFich.equals("CAR"))
    {
    while ((linea = br3.readLine()) != null)
    {

                array =linea.split(",");
                spliteado = array[0]+array[1]+array[2]+array[8];

                FileReader fh3 = new FileReader(cadena + lista2[0]);
                BufferedReader bh3 = new BufferedReader(fh3);

                find=0;

                while (((linea2 = bh3.readLine()) != null))

                {
                    array2 =linea2.split(",");
                    spliteado2 = array2[0]+array2[1]+array2[2]+array2[8];


                    if (spliteado.equals(spliteado2))
                    {

                        find =1;
                    }

                }
                if (find==0)

                {
                    bw3.write("+++++++++++++++++++++++++++++++++++++++++++");
                    bw3.newLine();
                    bw3.write("Se han incorporado los siguientes CGI en la nueva lista");
                    bw3.newLine();
                    bw3.write(linea);
                    bw3.newLine();
                    aparece=1;
                }
                bh3.close();


    }

我认为在Java中使用Set是一个不错的选择,如下面的帖子所示: Comparing two csv files in Java

但在我这样尝试之前,我想知道,如果有更好的选择。

谢谢大家。

3 个答案:

答案 0 :(得分:3)

就我可以解释您的代码而言,您需要找出第一个CSV文件中哪些行在第二个CSV文件中没有相等的行。正确的吗?

如果是这样,您只需将第二个CSV文件的所有行放入HashSet。像这样(Java 7代码):

Set<String> linesToCompare = new HashSet<>();
try (BufferedReader reader = new BufferedReader(new FileReader(cadena + lista2[0]))) {
    String line;
    while ((line = reader.readLine()) != null) {
        String[] splitted = line.split(",");
        linesToCompare.add(splitted[0] + splitted[1] + splitted[2] + splitted[8]);
    }
}

之后您可以简单地遍历第一个CSV文件中的行并进行比较:

try (BufferedReader reader = new BufferedReader(new FileReader(...))) {
    String line;
    while ((line = reader.readLine()) != null) {
        String[] splitted = line.split(",");
        String joined = splitted[0] + splitted[1] + splitted[2] + splitted[8];
        if (!linesToCompare.contains(joined)) {
            // handle missing line here
        }
    }
}

这符合您的需求吗?

答案 1 :(得分:1)

HashMap<String, String> file1Map = new HashMap<String, String>();

while ((String line = file1.readLine()) != null) {
  array =line.split(",");
  key = array[0]+array[1]+array[2]+array[8];
  file1Map.put(key, key);
}

while ((String line = file2.readLine()) != null) {
  array =line.split(",");
  key = array[0]+array[1]+array[2]+array[8];
  if (file1Map.containsKey(key)) {
    //if file1 has same line in file2
  }
  else {
    //if file1 doesn't have line like in file2
  }
}

答案 2 :(得分:0)

假设这一切都不适合内存我会首先将文件转换为它们的精简版本(el0,el1,el2,el8,orig-file-line-nr-for-reference-after)然后排序说文件。之后,您可以同时流式传输这两个文件并随时比较记录...从等式中排序,您只需要将它们“一次”进行比较。

但是我猜你可以使用一些允许在内存中进行排序和存储的List / Array对象来做同样的事情。除非元素非常大,否则40k记录对我来说确实听起来不是那么多。它的速度会更快。