BufferedReader readLine до завершения строки

У меня есть процесс (на самом деле веб-сервер), который записывает в файл журнала как POST, поступающий от клиентов.

Затем у меня есть отдельный процесс, который читает файл журнала, например (tail -f), в цикле:

            BufferedReader reader = new BufferedReader(new FileReader(logFilePath));
            String line = null;

            while (true)
            {
                    if ( (line = reader.readLine()) != null )
                    {
                            if (firstLine == null) firstLine = line;
                            processLine(line);
                            continue;
                    }

                    try
                    {
                            Thread.sleep(sleepTime);
                            long ts = System.currentTimeMillis();
                    } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                            break;
                    }
            }

Это работает очень хорошо в 99% случаев, но иногда строка, которую я читал с помощью BufferedReader.readLine, не является полной строкой. Я полагаю, это потому, что писатель (веб-сервер) еще не закончил сбрасывать все байты строки в файл.

Любые предложения, чтобы исправить или обойти это? Большое спасибо!


person Dexin Wang    schedule 24.02.2012    source источник
comment
У вас есть шаблон для обнаружения, когда линия не завершена?   -  person VirtualTroll    schedule 24.02.2012
comment
Просто быстрый указатель: вам не нужно использовать while (true) ... break, вы можете использовать переменную, чтобы проверить, следует ли вам продолжать.   -  person Viruzzo    schedule 24.02.2012
comment
Я думаю, что это может вам помочь: docs.oracle.com/javase/1.4.2/docs/api/java/io/   -  person nullpotent    schedule 24.02.2012
comment
Амин, да каждая строка это json. Поэтому, когда он неполный, это недопустимый json. Но следующий вызов readLine будет уже следующей строкой, а не кажется полной строкой.   -  person Dexin Wang    schedule 25.02.2012


Ответы (2)


Поработав с несколькими процессами, которым требуется доступ к одному файлу примерно в одно и то же время (часто один процесс следует за другим), я обнаружил (вместе с другими разработчиками, с которыми я работал), что файл «трейлера» хорош для использования. чтобы указать, когда один процесс завершил взаимодействие с файлом, к которому должен получить доступ другой процесс.

Я не уверен, как часто ваш веб-сервер записывает в этот журнал, а также как быстро ваш процесс Java должен его прочитать, но если есть время, которое может пройти между доступом каждого процесса к файлу, может быть записан файл трейлера, который указывает когда ваш веб-сервер закончит запись в файл. Ваш процесс Java может сначала проверить, существует ли файл трейлера, а затем, найдя его, удалить, а затем прочитать из журнала.

В противном случае вам может понадобиться использовать команды ОС, чтобы узнать, записывает ли ваш веб-сервер запись в журнал, и запускать программу чтения журнала только в том случае, если это не так. http://blog.bensmann.com/executing-operating-system-commands содержит полезную информацию о выполнении команд ОС в Java.

Суть в том, что должен быть установлен какой-то прочный зазор, чтобы эти процессы не читали/записывали журнал одновременно.

person Zack Macomber    schedule 24.02.2012
comment
Спасибо, Зак. Веб-сервер пишет довольно быстро, пару строк и несколько тысяч байт каждую секунду, и он растет. Не уверен, что будет дорого проверить, закончил ли запись веб-сервер. На самом деле я не возражаю против того, чтобы читатель немного отставал от автора, если это поможет, но не знаю, как это сделать. - person Dexin Wang; 25.02.2012

Недавно я столкнулся с той же проблемой. Позвольте мне объяснить, когда буферный считыватель будет читать неполную строку с помощью метода readline(). Он сделает это, когда встретит EOF перед возвратом каретки.

Код в BufferedReader Readine выглядит следующим образом

 if (nextChar >= nChars)
                    fill();
                if (nextChar >= nChars) { /* EOF */
                    if (s != null && s.length() > 0)
                        return s.toString();

                    else
                        return null;
                }

Это говорит о том, что если он встретит EOF до возврата каретки, он вернет все, что уже прочитал. Но правильный код должен быть, когда мы делаем вызов readLine() и символ EOF встречается до возврата каретки, он должен возвращать NULL вместо неполной строки.

Я написал свой расширенный класс bufferedreader, в котором ReadLine возвращает NULL в сценарии, описанном выше.

person Puneet    schedule 20.12.2012
comment
Что такое символ EOF? - person David Schwartz; 06.06.2016
comment
В приведенном вами коде нет ничего о символе EOF. Нет символа EOF. Существует условие EOF. - person user207421; 06.06.2016