В настоящее время у меня есть 2 BufferedReader, инициализированных в одном текстовом файле. Когда я закончу читать текстовый файл с первым BufferedReader, я использую второй, чтобы еще раз пройти через файл сверху. Необходимо несколько проходов через один и тот же файл.
Я знаю о reset(), но ему нужно предшествовать вызов mark(), а mark() должен знать размер файла, и я не думаю, что мне следует с этим беспокоиться.
Идеи? Пакеты? Библиотеки? Код?
Спасибо TJ




В чем недостаток простого создания нового BufferedReader для чтения сверху? Я ожидаю, что операционная система кэширует файл, если он достаточно мал.
Если вас беспокоит производительность, вы доказали, что она является узким местом? Я бы просто сделал самое простое и не беспокоился об этом, пока у вас не будет для этого особой причины. Я имею в виду, что вы можете просто прочитать все это в памяти, а затем выполнить два прохода по результату, но, опять же, это будет сложнее, чем просто прочитать с самого начала заново с новым читателем.
Буферизованные считыватели предназначены для последовательного чтения файла. То, что вы ищете, - это java.io.RandomAccessFile, и затем вы можете использовать seek(), чтобы переместить вас туда, где вы хотите в файле.
Считыватель произвольного доступа реализован так:
try{
String fileName = "c:/myraffile.txt";
File file = new File(fileName);
RandomAccessFile raf = new RandomAccessFile(file, "rw");
raf.readChar();
raf.seek(0);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
"rw" - это символ режима, который является подробно здесь.
Причина, по которой считыватели с последовательным доступом настроены таким образом, заключается в том, что они могут реализовать свои буферы и что что-то не может быть изменено под их ногами. Например, считыватель файлов, предоставляемый буферизованному считывателю, должен работать только с этим буферизованным считывателем. Если бы было другое место, которое могло повлиять на это, у вас могла бы быть непоследовательная работа, так как один считыватель продвинул свою позицию в считывателе файлов, в то время как другой хотел, чтобы он оставался прежним, теперь вы используете другой считыватель, и он находится в неопределенном месте.
Лучший способ продолжить - изменить алгоритм таким образом, чтобы второй проход вам НЕ понадобился. Я использовал этот подход пару раз, когда мне приходилось иметь дело с огромными (но не ужасными, то есть несколькими гигабайтами) файлами, которые не умещались в доступной памяти.
Это может быть сложно, но повышение производительности обычно стоит затраченных усилий.
В настоящее время я предполагаю, что вы имеете в виду 30 ГБ, если только вы не используете действительно небольшой встроенный hw (но тогда он был бы бездисковым). В любом случае случайный поиск на дисках часто полностью разрушает логарифмическую производительность двоичного поиска. Есть несколько альтернатив: 1) выполнение последовательного доступа (да, на диске последовательный поиск может быть быстрее, чем двоичный поиск) или 2) смешанный подход, такой как использование B-дерева en.wikipedia.org/wiki/B-tree. Если этих подсказок недостаточно, вы можете захотеть сформулируйте свой вопрос как отдельный, а не комментарий (пожалуйста, оставьте здесь комментарий со ссылкой на вопрос, чтобы пинговать меня)
«Вся эта история с mark () и reset () в BufferedReader попахивает плохим дизайном».
почему бы вам не расширить этот класс и не сделать метку () в конструкторе (), а затем выполнить поиск (0) в методе topOfFile ().
BR,
~ А
О отметке / сбросе:
Метод метки в BufferedReader принимает параметр readAheadLimit, который ограничивает расстояние, которое вы можете прочитать после метки, прежде чем сброс станет невозможным. Сброс на самом деле не означает поиск файловой системы (0), он просто ищет внутри буфера. Процитируем Javadoc:
readAheadLimit - Limit on the number of characters that may be read while still preserving the mark. After reading this many characters, attempting to reset the stream may fail. A limit value larger than the size of the input buffer will cause a new buffer to be allocated whose size is no smaller than limit. Therefore large values should be used with care.
Не могли бы вы уточнить? У меня есть файл размером 30 МБ, я не могу загрузить его в память. Я отсортировал данные и теперь хочу выполнить двоичный поиск непосредственно в файле. Для этого мне нужно случайным образом искать.