逐行合并两个文件

时间:2018-10-31 12:42:28

标签: java

是否有比我目前使用的更有效的方法,将文件2的行追加到文件1的行接一行地合并两个文件?

如果file1包含

a2
b2
c2

并且file2包含

a1,a2
b1,b2
c1,c2

然后输出文件应包含

private FileSheet combineRecords(ArrayList<FileSheet> toCombine) throws IOException
{
    ArrayList<String> filepaths = new ArrayList<String>();

    for (FileSheet sheetIterator : toCombine)
    {
        filepaths.add(sheetIterator.filepath);
    }

    String filepathAddition = "";

    for (String s : filepaths)
    {
        filepathAddition = filepathAddition + s.split(".select.")[1].replace(".csv", "")  + ".";
    }

    String outputFilepath = subsheetDirectory + fileHandle.getName().split(".csv")[0] + ".select." + filepathAddition +  "csv";

    Log.log("Output filepath "  + outputFilepath);

    long mainFileLength = toCombine.get(0).recordCount();

    for (FileSheet f : toCombine)
    {
        int ordinal = toCombine.indexOf(f);

        if (toCombine.get(ordinal).recordCount() != mainFileLength)
        {
            Log.log("Error : Record counts for 0 + " + ordinal);
            return null;
        }
    }

    FileSheet finalValues;

    Log.log("Starting iteration streams");
    BufferedWriter out = new BufferedWriter(new FileWriter(outputFilepath, false));

    List<BufferedReader> streams = new ArrayList<>();
    for (FileSheet j : toCombine)
    {
        streams.add(new BufferedReader(new FileReader(j.filepath)));
    }

    String finalWrite = "";

    for (int i = 0; i < toCombine.get(0).recordCount(); i++)
    {

        for (FileSheet j : toCombine)
        {
            int ordinal = toCombine.indexOf(j);

            finalWrite = finalWrite + streams.get(ordinal).readLine();

            if (toCombine.indexOf(j) != toCombine.size() - 1)
            {
                finalWrite = finalWrite + ",";
            }
            else
            {
                finalWrite = finalWrite + "\n";
            }
        }

        if (i % 1000 == 0 || i == toCombine.get(0).recordCount() - 1)
        {
            // out.write(finalWrite + "\n");
            Files.write(Paths.get(outputFilepath),(finalWrite).getBytes(),StandardOpenOption.APPEND);

            finalWrite = "";
        }           
    }
    out.close();


    Log.log("Finished combineRecords");

    finalValues = new FileSheet(outputFilepath,0);
    return finalValues;
}

当前的CombineRecords方法类似于

streams.get(ordinal).skip(i).findFirst().get();

我已经尝试过bufferedwriters和files.write,它们创建文件3的时间都差不多,都是在1:30分钟的范围内,但是我不确定瓶颈是在读写方面

我正在使用的样本文件目前有36,000条记录,但是我将使用的实际文件为〜650,000,因此采取1625秒(如果线性缩放)对于此操作是完全不可行的

编辑:我修改了代码,只打开了一次文件,而不是每次迭代,但是现在我跳到第n行时就关闭了流。 我认为通过执行{{1}}会返回一个新的流,而不是跳过然后关闭该流

编辑2:修改了代码以使用bufferedreaders而不是流,并且每读取1000行就向文件写入一次,这就确定了瓶颈正在读取,因为它仍然需要〜1:30来完成

1 个答案:

答案 0 :(得分:1)

首先在没有循环的情况下使用+运算符来结束字符串。但是,当您要在循环中合并字符串时,应使用StringBuilder以获得更好的性能。

您可以改善的第二件事可以像下面这样写到文件末尾:

StringBuilder finalWrite = new StringBuilder();
for (int i = 0; i < toCombine.get(0).recordCount(); i++)
{

    for (FileSheet j : toCombine)
    {
        int ordinal = toCombine.indexOf(j);

        finalWrite.append(streams.get(ordinal).readLine());

        if (toCombine.indexOf(j) != toCombine.size() - 1)
        {
            finalWrite.append(",");
        }
        else
        {
            finalWrite.append("\n");
        }
    }           
}

Files.write(Paths.get(outputFilepath), finalWrite.toString().getBytes());