2

私のアプリケーションでは、カスタムの「readline」メソッドを作成する必要がありました。これは、ASCII テキスト ファイルで改行の末尾を検出して保存したかったからです。JavareadLine()メソッドは、どの改行シーケンス ( \r\n\r\n) が検出されたかEOFを通知しないため、変更されたファイルに書き込むときにまったく同じ改行シーケンスを配置することはできません。

これが私のテスト例の SSCE です。

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

バージョン 1 は を使用しますreadLine()が、バージョン 2 は改行文字を保持する私のバージョンです。

約 50 万行のテキスト ファイルでは、バージョン 1 は約 380 ミリ秒、バージョン 2 は 1074 ミリ秒かかります。

version2 のパフォーマンスを高速化するにはどうすればよいですか?

Google guava および apache-commons ライブラリを確認しましたが、テキスト ファイルの読み取り時にどの改行文字が検出されたかを示す "readLine()" の適切な代替が見つかりません。

4

4 に答える 4

2

2 番目のバージョンは、BufferedReader または別の形式のバッファーを使用していないようです。速度低下の原因となる場合があります。

メモリ内のファイル全体を読み取るように見えるので、おそらくそれを大きな文字列として (バッファを使用して) 読み取り、メモリ内で解析して行末を分析できます。

于 2012-11-19T16:40:51.407 に答える
1

あなたは out ステートメントを2倍にしています( one for line and one for newline):

以下を試すことができますか(lineSeparator()行区切りを取得し、書き込む前に追加するために使用します):

        out.write(lineArray.get(i)+System.lineSeparator());
于 2012-11-19T16:45:53.093 に答える
0

車輪を再発明しないでください。
BufferedReader#readLine() コードを確認します
コピーして貼り付け、必要な変更を加えて、行セパレーターを行内に保持します

于 2012-11-23T21:11:01.927 に答える