Java: чтение последних n строк файла HUGE

Я хочу прочитать последние n строк очень большого файла, не читая весь файл в любой буфер / область памяти с помощью Java.

Я просмотрел API JDK и Apache Commons I / O и не смог найти подходящий для этой цели.

Я думал о том, как хвост или меньше работает в UNIX. Я не думаю, что они загружают весь файл, а затем показывают последние несколько строк файла. Аналогичный способ должен быть аналогичным для Java.

    9 Solutions collect form web for “Java: чтение последних n строк файла HUGE”

    Если вы используете RandomAccessFile , вы можете использовать length и seek чтобы добраться до определенной точки ближе к концу файла, а затем читать вперед.

    Если вы обнаружите, что линий недостаточно, вернитесь назад и повторите попытку. Как только вы выяснили, где начинается N я последняя строка, вы можете искать там и просто читать и печатать.

    Исходное предположение наилучшего предположения может быть сделано на основе ваших свойств данных. Например, если это текстовый файл, возможно, длина строк не будет превышать в среднем 132, поэтому, чтобы получить последние пять строк, запустите до 660 символов до конца. Затем, если вы ошиблись, попробуйте еще раз в 1320 (вы можете использовать то, что вы узнали из последних 660 символов, чтобы настроить это: например: если эти 660 символов были всего тремя строками, следующая попытка может быть 660/3 * 5, плюс, может быть, немного больше на всякий случай).

    Я нашел его самым простым способом, используя ReversedLinesFileReader от apache commons-io api. Этот метод даст вам строку снизу вверх, а вы можете указать значение n_lines чтобы указать количество строк.

     import org.apache.commons.io.input.ReversedLinesFileReader; File file = new File("D:\\file_name.xml"); int n_lines = 10; int counter = 0; ReversedLinesFileReader object = new ReversedLinesFileReader(file); while(counter < n_lines) { System.out.println(object.readLine()); counter++; } 

    RandomAccessFile – хорошее место для начала, как описано в других ответах. Однако есть одно важное предостережение .

    Если ваш файл не закодирован с однобайтовой кодировкой, метод readLine() не будет работать для вас. И readUTF() не будет работать ни при каких обстоятельствах. (Он читает строку, которой предшествует число символов …)

    Вместо этого вам нужно будет убедиться, что вы ищете маркеры конца строки таким образом, чтобы соблюдались границы символов кодировки. Для кодировок с фиксированной длиной (например, вкусов UTF-16 или UTF-32) вам необходимо извлечь символы, начиная с позиций байтов, которые делятся на размер символа в байтах. Для кодировок с переменной длиной (например, UTF-8) вам необходимо выполнить поиск байта, который должен быть первым байтом символа.

    В случае UTF-8 первый байт символа будет 0xxxxxxx или 110xxxxx или 1110xxxx или 11110xxx . Все остальное является либо вторым / третьим байтом, либо незаконной последовательностью UTF-8. См . Стандарт Unicode, версия 5.2, глава 3.9 , таблица 3-7. Это означает, что, как указывает обсуждение комментариев, любые байты 0x0A и 0x0D в правильно закодированном streamе UTF-8 будут представлять символ LF или CR. Таким образом, подсчет байтов является допустимой страtagsей реализации (для UTF-8).

    Определив правильную границу символа, вы можете просто вызвать new String(...) передающую массив байтов, смещение, подсчет и кодировку, а затем повторно вызвать String.lastIndexOf(...) для подсчета конца строк.

    Я обнаружил, что RandomAccessFile и другие classы Buffer Reader слишком медленны для меня. Ничто не может быть быстрее tail -< #lines> . Так что это было лучшим решением для меня.

     public String getLastNLogLines(File file, int nLines) { StringBuilder s = new StringBuilder(); try { Process p = Runtime.getRuntime().exec("tail -"+nLines+" "+file); java.io.BufferedReader input = new java.io.BufferedReader(new java.io.InputStreamReader(p.getInputStream())); String line = null; //Here we first read the next line into the variable //line and then check for the EOF condition, which //is the return value of null while((line = input.readLine()) != null){ s.append(line+'\n'); } } catch (java.io.IOException e) { e.printStackTrace(); } return s.toString(); } 

    CircularFifoBuffer из сообщества apache. ответьте на аналогичный вопрос, как читать последние 5 строк .txt-файла в java

    Обратите внимание, что в Apache Commons Collections 4 этот class, похоже, был переименован в CircularFifoQueue

    RandomAccessFile позволяет искать (http://download.oracle.com/javase/1.4.2/docs/api/java/io/RandomAccessFile.html). Метод File.length вернет размер файла. Проблема заключается в определении количества строк. Для этого вы можете искать конец файла и читать назад, пока не нажмете нужное количество строк.

    У меня была схожая проблема, но я не понял других решений.

    Я использовал это. Надеюсь, это простой код.

     // String filePathName = (direction and file name). File f = new File(filePathName); long fileLength = f.length(); // Take size of file [bites]. long fileLength_toRead = 0; if (fileLength > 2000) { // My file content is a table, I know one row has about eg 100 bites / characters. // I used 1000 bites before file end to point where start read. // If you don't know line length, use @paxdiablo advice. fileLength_toRead = fileLength - 1000; } try (RandomAccessFile raf = new RandomAccessFile(filePathName, "r")) { // This row manage open and close file. raf.seek(fileLength_toRead); // File will begin read at this bite. String rowInFile = raf.readLine(); // First readed line usualy is not whole, I needn't it. rowInFile = raf.readLine(); while (rowInFile != null) { // Here I can readed lines (rowInFile) add to String[] array or ArriyList. // Later I can work with rows from array - last row is sometimes empty, etc. rowInFile = raf.readLine(); } } catch (IOException e) { // } 

    Вот лучший способ, который я нашел для этого. Простая и довольно быстрая и эффективная память.

     public static void tail(File src, OutputStream out, int maxLines) throws FileNotFoundException, IOException { BufferedReader reader = new BufferedReader(new FileReader(src)); String[] lines = new String[maxLines]; int lastNdx = 0; for (String line=reader.readLine(); line != null; line=reader.readLine()) { if (lastNdx == lines.length) { lastNdx = 0; } lines[lastNdx++] = line; } OutputStreamWriter writer = new OutputStreamWriter(out); for (int ndx=lastNdx; ndx != lastNdx-1; ndx++) { if (ndx == lines.length) { ndx = 0; } writer.write(lines[ndx]); writer.write("\n"); } writer.flush(); } 
      int n_lines = 1000; ReversedLinesFileReader object = new ReversedLinesFileReader(new File(path)); String result=""; for(int i=0;i 
    Interesting Posts

    Случайно dd'ed изображение к неправильному диску / переписал таблицу разделов + начало раздела NTFS

    R: Маскированные функции

    Как добавить виртуальные сетевые адаптеры на мой Linux-ПК, чтобы они отображали свои MAC-адреса в домене ISP?

    Лучшая практика для вложенных fragmentов в Android 4.0, 4.1 (<4.2) без использования библиотеки поддержки

    Почему глобальные и статические переменные инициализируются значениями по умолчанию?

    startLeScan с 128-битными UUID не работает в собственной реализации BLE на Android

    Восстановление файла Linux

    Есть ли шаблон для настройки правила Outlook 2007?

    Замена 32-битного счетчика циклов на 64-битные значения приводит к сумасшедшим отклонениям производительности

    Как свернуть разделы кода в Visual Studio Code для Windows

    Почему загрузка формы не может устранить исключение?

    Почему браузер не может отправлять запрос gzip?

    Вывод файла изображения из сервлета

    Spring Java Config vs Jboss 7

    Как запустить графические программы Linux из командной строки, но отдельно от командной строки?

    Давайте будем гением компьютера.