Задать вопрос
Den4xCode
@Den4xCode
Coder

Какой самый быстрый способ прочитать/записать из большого файла?

Есть текстовый файл input.txt, количество строк до 10^5, размер строки 2 и 3 может достигать 10^9 различных эл-ов. остальные строки могут повторятся между собой и их размер 5 эл-ов.

Я использую следующий код:

static String[] getStrings(String fileName) throws Exception {

        BufferedReader bufferedReader = new BufferedReader(new FileReader(fileName));
        StringBuilder stringBuilder = new StringBuilder();

        String line;
        while ((line = bufferedReader.readLine()) != null) {
            stringBuilder.append(line).append("\n");
        }

//плохая строчка, создает для каждого эл-та строковый объект в куче.
        String[] all_lines = stringBuilder.toString().split("\n");

        bufferedReader.close();

        return all_lines;

    }


Также использовал split() для 2 и 3 строки, что супер не хорошо, ведь при таком коде у меня для млрд элементов в куче создавалось млрд строковых объектов, а это гг для производительности программы.

Наверное нужно использовать byteBuffer, но у меня уже каша в голове, так как сёрфил инет в поисках лучшего решения и слишком много различных выборов на которых нет времени тестировать, если не сложно подскажите решение лучшее на ваш взгляд, буду очень признателен.

Основная задача: максимально быстро прочитать с файла, для 2 и 3 строки нужно интерпретировать как числа, чтобы я мог в дальнейшем обращаться к ним через стек, а не через строки, максимально быстро записать в файл ответ программы.

2 и 3 строки вида: "1 2 33 4 107 11 1000 1007" и т.д. до 10^9 эл-ов.

650ac8bb837f2121157333.png

P.S.:
Вроде бы быстрейший способ это чтение через off-heap метод, а запись через directBuffer, но у меня мало опыта в этом и не уверен что это подходит к конкретно к этой задачи.
  • Вопрос задан
  • 390 просмотров
Подписаться 1 Простой 1 комментарий
Пригласить эксперта
Ответы на вопрос 2
sergey-gornostaev
@sergey-gornostaev Куратор тега Java
Седой и строгий
Быстрота вне контекста смысла не имеет. Сам по себе вызов FileReader.readLine() достаточно быстрый, чтобы упираться в скорость передачи данных диска. Если вам не хватает скорости, то надо профилировать код, искать узкие места и оптимизировать их. Если узких мест нет, всё работает на пределе возможностей, то придётся смотреть в сторону распределённой обработки данных.

P.S. Обращение к нативной памяти не быстрее, чем к куче, а вот выделяется она на много медленнее, так что в общем случае direct buffer вам не поможет. Если проблема со скоростью только в аллокациях и от них можно отказаться,, например при сквозной передаче считанного с диска в сеть, то стоит использовать канал и zero copy через DMA.
Ответ написан
@D4nDme
Не джавист, но в цикле можно сразу добавлять строку в массив, а не в стрингбилдер, тогда и сплит не понадобится. Если же имелось ввиду, что все строки будут обрабатываться как единая String, то было бы лучше получать строку с интами из общей String с помощью метода выделения подстроки какого-нибудь, для этого надо будет запомнить длины соответствующих строк, чтобы найти индексы начала и конца 2х подстрок.
P.S. Прочитал задачу, тут можно еще проще сделать:

intString0 = bufferedReader.readLine();
intString1 = bufferedReader.readLine();
intString2 = bufferedReader.readLine();
int Q = SomeAnalyzer(intString0);
String[] hands;
int i = 0;
while (i < Q) {
    hands.SomeAppendMethod(bufferedReader.readLine());
    i += 1;
}


Еще проще было бы читать из потока ввода сразу в переменные M, N, Q и т.д. Но, видимо, у автора была причина так не делать.
Надеюсь, кому-то будет полезно, кто решает такие задачи.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы