Java iguala / supera el rendimiento de readline

Para mi aplicación, tuve que escribir un método personalizado de "línea de lectura" ya que quería detectar y preservar las terminaciones de nueva línea en un archivo de texto ASCII. El Java readLine()método no le dice qué secuencia de nueva línea ( \r, \n, \r\n) o EOFse encontró, así que no puedo poner exactamente la misma secuencia de nueva línea al escribir en el archivo modificado.

Aquí está el SSCE de mi ejemplo de prueba.

public class TestLineIO {
    public static java.util.ArrayList<String> readLineArrayFromFile1(java.io.File file) {
        java.util.ArrayList<String> lineArray = new java.util.ArrayList<String>();
        try {
            java.io.BufferedReader br = new java.io.BufferedReader(new java.io.FileReader(file));
            String strLine;
            while ((strLine = br.readLine()) != null) {
                lineArray.add(strLine);
            }
            br.close();
        } catch (java.io.IOException e) {
            System.err.println("Could not read file");
            System.err.println(e);
        }
        lineArray.trimToSize();
        return lineArray;
    }


    public static boolean writeLineArrayToFile1(java.util.ArrayList<String> lineArray, java.io.File file) {
        try {
            java.io.BufferedWriter out = new java.io.BufferedWriter(new java.io.FileWriter(file));
            int size = lineArray.size();
            for (int i = 0; i < size; i++) {
                out.write(lineArray.get(i));
                out.newLine();
            }
            out.close();
        } catch (java.io.IOException e) {
            System.err.println("Could not write file");
            System.err.println(e);
            return false;
        }
        return true;
    }


    public static java.util.ArrayList<String> readLineArrayFromFile2(java.io.File file) {
        java.util.ArrayList<String> lineArray = new java.util.ArrayList<String>();
        try {
            java.io.FileInputStream stream = new java.io.FileInputStream(file);
            try {
                java.nio.channels.FileChannel fc = stream.getChannel();
                java.nio.MappedByteBuffer bb = fc.map(java.nio.channels.FileChannel.MapMode.READ_ONLY, 0, fc.size());
                char[] fileArray = java.nio.charset.Charset.defaultCharset().decode(bb).array();
                if (fileArray == null || fileArray.length == 0) {
                    return lineArray;
                }
                int length = fileArray.length;
                int start = 0;
                int index = 0;
                while (index < length) {
                    if (fileArray[index] == '\n') {
                        lineArray.add(new String(fileArray, start, index - start + 1));
                        start = index + 1;
                    } else if (fileArray[index] == '\r') {
                        if (index == length - 1) { //last character in the file
                            lineArray.add(new String(fileArray, start, length - start));
                            start = length;
                            break;
                        } else {
                            if (fileArray[index + 1] == '\n') {
                                lineArray.add(new String(fileArray, start, index - start + 2));
                                start = index + 2;
                                index++;
                            } else {
                                lineArray.add(new String(fileArray, start, index - start + 1));
                                start = index + 1;
                            }
                        }
                    }
                    index++;
                }
                if (start < length) {
                    lineArray.add(new String(fileArray, start, length - start));
                }
            } finally {
                stream.close();
            }
        } catch (java.io.IOException e) {
            System.err.println("Could not read file");
            System.err.println(e);
            e.printStackTrace();
            return lineArray;
        }
        lineArray.trimToSize();
        return lineArray;
    }


    public static boolean writeLineArrayToFile2(java.util.ArrayList<String> lineArray, java.io.File file) {
        try {
            java.io.BufferedWriter out = new java.io.BufferedWriter(new java.io.FileWriter(file));
            int size = lineArray.size();
            for (int i = 0; i < size; i++) {
                out.write(lineArray.get(i));
            }
            out.close();
        } catch (java.io.IOException e) {
            System.err.println("Could not write file");
            System.err.println(e);
            return false;
        }
        return true;
    }


    public static void main(String[] args) {
        System.out.println("Begin");
        String fileName = "test.txt";
        long start = 0;
        long stop = 0;

        start = java.util.Calendar.getInstance().getTimeInMillis();
        java.io.File f = new java.io.File(fileName);
        java.util.ArrayList<String> javaLineArray = readLineArrayFromFile1(f);
        stop = java.util.Calendar.getInstance().getTimeInMillis();
        System.out.println("Total time = " + (stop - start) + " ms");       
        java.io.File oj = new java.io.File(fileName + "_readline.txt");
        writeLineArrayToFile1(javaLineArray, oj);

        start = java.util.Calendar.getInstance().getTimeInMillis();
        java.util.ArrayList<String> myLineArray = readLineArrayFromFile2(f);
        stop = java.util.Calendar.getInstance().getTimeInMillis();
        System.out.println("Total time = " + (stop - start) + " ms");       
        java.io.File om = new java.io.File(fileName + "_custom.txt");
        writeLineArrayToFile2(myLineArray, om);

        System.out.println("End");
    }
}

La versión 1 usa readLine(), mientras que la versión 2 es mi versión, que conserva los caracteres de nueva línea.

En un archivo de texto con aproximadamente 500K líneas, la versión 1 tarda unos 380 ms, mientras que la versión 2 tarda 1074 ms.

¿Cómo puedo acelerar el rendimiento de la versión 2?

Revisé las bibliotecas de guayaba y apache-commons de Google, pero no puedo encontrar un reemplazo adecuado para "readLine ()" que indique qué carácter de nueva línea se encontró al leer un archivo de texto.

Respuesta 1

Estás duplicando las declaraciones ( one for line and one for newline):

¿Puede probar a continuación (use lineSeparator()para obtener el separador de línea y agregar antes de escribir):

        out.write(lineArray.get(i)+System.lineSeparator());
Respuesta: 2

Eclipse da sugerencias que comienzan con lo que escribo: Pero IntelliJ IDEA da sugerencias que tienen (en el medio o al principio) lo que escribo: supongo que Eclipse Luna tiene la misma característica (basada ...

En Guava 10+, Google desaprobó Files.deleteDirectoryContents (). JavaDoc dice obsoleto. Este método adolece de una pobre detección de enlaces simbólicos y condiciones de carrera. Esta funcionalidad puede ser compatible ...

Tengo esta situación en la que tengo una relación padre-hijo entre dos conjuntos de datos. Tengo una colección de documentos primarios y una colección de documentos secundarios. El requisito es que los padres y ...

Con AWT, ¿cómo importa una imagen en un rectángulo que ha dibujado? Quiero asignar el fondo solo a ese rectángulo en particular.