Читайте каждую строку файла, используя MappedByteBuffer в java - PullRequest
0 голосов
/ 04 мая 2020

Я работаю над задачей, в которой мне нужно прочитать огромный файл (размером ~ 1,5 ГБ и приблизительно 16000000 записей). Передо мной два варианта:

  1. использовать BufferReader, где я могу получить каждую строку в строке.
  2. использовать MappedByteBuffer с FileChannel и RandomAccessFile.

В сыром тесте читать нет. записей с опцией 1, это занимает около 2900 мс, а в варианте 2 это занимает около 1450 мс.

Тестовые программы следующие:

Опция 1:

public static void reviewBufferedReader () {
    long lineNumber = 0;
    String line = null;
    try (BufferedReader b = Files.newBufferedReader(Paths.get("D:\\\\Temp Data Files\\Data1.txt"), StandardCharsets.UTF_8)) {
        executor = RecordsDistributionExecutor.getInstance();
        while ((line = b.readLine()) != null) {
            lineNumber++;
        }
    } catch (Exception e) {
        System.err.println("Error in reviewBufferedReader : "+e.getMessage());
    } finally {

    }
    System.out.println("Total no. of lines: "+lineNumber);
}

Вариант 2:

public static void reviewFileChannelWithMappedByteBuffer () {
    long lineNumber = 0;
    try (RandomAccessFile raFile = new RandomAccessFile("D:\\\\Temp Data Files\\Data2.txt", "r");
            FileChannel inChannel = raFile.getChannel();){
        MappedByteBuffer buffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
        buffer.load(); 
        char c;
        for(int i = 0; i< buffer.limit(); i++) {
            c = (char) buffer.get();
            if ('\n' == c) {
                lineNumber++;
            }
        }
        buffer.clear(); // do something with the data and clear/compact it.
    } catch (Exception e) {
        System.err.println("Error in reviewFileChannelWithMappedByteBuffer : "+e.getMessage());
    } finally {

    }
    System.out.println("Total no. of lines: "+lineNumber);
}

Как я уже сказал, Вариант 2 занимает меньше времени при базовом c тестировании.

У меня вопрос, возможно ли прочитать данные файла строка за строкой в ​​варианте 2, как вариант 1.

Спасибо,

Атул

1 Ответ

0 голосов
/ 05 мая 2020

Я изменил свой ответ после комментариев пользователя 207421.Мы рекомендуем использовать BufferedReader с большим размером буфера по умолчанию, не помогает:

 try(var reader = new BufferedReader(new FileReader(file), 128  * 1024)) { ... }

Если с памятью нет проблем, Files.readAllBytes был быстрее Мой P C для подсчета строк тестового файла объемом 0,5 ГБ, чтения из NAS или SSD:

int lines = 0;
for (var b : Files.readAllBytes(f))
    if (b == '\n') lines++;

FileInputStream не сильно отстал и требует меньше памяти:

int len = 0, lines = 0;
byte[] buffer = new byte[128 * 1024];
try(var in = new FileInputStream(f)) {
    while (( len = in.read(buffer)) >= 0) {
        for (int x = len - 1 ; x >= 0 ; x--) {
            if (buffer[x] == '\n') lines++;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...