Fusionar dos archivos línea por línea Java

¿Hay alguna forma más eficiente que la que estoy usando actualmente para fusionar dos archivos línea por línea agregando la línea del archivo2 al archivo1?

Si el archivo 1 contiene

a1
b1
c1

Y file2 contiene

a2
b2
c2

Entonces el archivo de salida debe contener

a1,a2
b1,b2
c1,c2

El método actual combineRecords se parece a

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;
}

He intentado tanto escritores almacenados en memoria intermedia como files.write, y tienen tiempos similares para crear file3, ambos en el rango de 1:30 minutos, pero no estoy seguro de si el cuello de botella está en la lectura o escritura

Los archivos de muestra que estoy usando actualmente tienen 36,000 registros, pero el archivo real que usaré es ~ 650,000, por lo que tomar (si se escala linealmente) 1625 segundos es completamente inviable para esta operación

Editar: he modificado el código para abrir solo archivos una vez, en lugar de por iteración, sin embargo, ahora estoy cerrando la transmisión al saltar a la enésima línea, pensé que al hacerlo streams.get(ordinal).skip(i).findFirst().get();devolvería una nueva transmisión en lugar de omitir y luego cerrar la transmisión

Edición 2: modificó el código para usar lectores almacenados en búfer en lugar de secuencias, y escribir en el archivo cada 1000 líneas leídas, y eso determinó que el cuello de botella está leyendo, porque todavía se necesitan ~ 1:30 para hacerlo

Respuesta 1

Estoy tratando de implementar la codificación MP3 en Android usando la biblioteca LAME siguiendo estas guías: Lame MP3 Encoder compile para Android http: //developer.samsung.com/android/technical-docs/Porting-and -...

Tengo un método privado genérico que realiza tareas comunes y es utilizado por otros métodos. El método genérico tiene condiciones if y else para admitir otros métodos que se llaman. Ejemplo: vacío privado ...

Me gustaría manejar errores con excepciones (sin marcar). Escuché que para cada tipo de excepción debería crear una subclase de Error o RuntimeException. ¿Cual es la diferencia?

Quiero adaptar slf4j con Logback en una aplicación heredada. Lo bueno es que la aplicación heredada tiene su propio marco de registro. Entonces, todo lo que tuve que hacer es alterar el marco de registro para iniciar sesión en slf4j ...