У меня есть файл журнала, который постоянно пополняется новыми строками данных. Мне нужно получить новые добавленные данные в java, как только они будут написаны. На данный момент мое решение:
public static void readNonStop(String filename, boolean goToEnd, FileReadCallback readCallback) {
if (readCallback == null) {
return;
}
try {
BufferedReader br = new BufferedReader(new FileReader(filename));
try {
String line = br.readLine();
int lineNumber = 0;
if (goToEnd) {
while(br.readLine() != null) {}
}
while (true) {
if (line != null) {
readCallback.onRead(lineNumber++, line);
} else {
Thread.sleep(1);
}
line = br.readLine();
}
} finally {
br.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
Но я чувствую, что должен быть способ получше. Мне не нравится идея постоянного цикла выполнения со «сном» внутри, и я бы предпочел какой-то подход, управляемый событиями.
Если я полагаюсь на события FileSystem для повторного открытия файла каждый раз, когда он изменяется, это вызывает задержку.
Как правильно это сделать в данной ситуации?
Заранее спасибо!
Вы смотрели Java Watch Service. Это лучше, чем пытаться реализовать свою собственную логику. Взгляните на эту публикацию - stackoverflow.com/questions/16251273/…
В настоящее время я использую WatchService, но проблема в том, что это вызывает задержку, потому что вам нужно постоянно открывать и закрывать файл. Данные нужны как можно скорее.
Вы пробовали Apache Commons TailerListener? Документация Javadoc: commons.apache.org/proper/commons-io/apidocs/org/apache/comm ons /… Реализация: commons.apache.org/proper/commons-io/apidocs/src-html/org/…




Файлы не предназначены для обмена сообщениями. Даже при использовании TCP по шлейфу задержка может составлять 10–30 микросекунд. Без изменения формата файла ваше решение, вероятно, будет самым быстрым.
ПРИМЕЧАНИЕ: вам не нужно спать целую миллисекунду. Вы можете использовать Thread.yield() или LockSupport.parkNanos(100_000);. Для более сложной стратегии вы можете иметь такой класс, как LongPauser, который отключается настраиваемым образом.
Кстати, я реализовал решение для записи / чтения файлов с низкой задержкой, которое называется Chronicle Queue. У этого есть субмикросекундные задержки с использованием двоичного формата для скорости.
ПРИМЕЧАНИЕ. Можно просто до конца, пропустив все байты available(), когда вы открываете файл как FileInputStream. Это может привести к неполной строке в зависимости от того, как работает ваша буферизация.
Спасибо за Ваш ответ. В настоящее время единственное, что мне не нравится в этом решении, - это нагрузка на ЦП, если нет "Thread.sleep". По крайней мере, при 1 миллисекунде сна загрузка ЦП снижается с 40% до 0-1%. Использование WatchService в некоторых случаях приводит к задержке до 5-6 секунд, что недопустимо. Дело в том, что это единственный способ получить необходимую информацию, поэтому у меня нет возможности переключать способы связи. Вместо этого я должен использовать FileInputStream.
Вы можете поспать дольше 10 мс. LongPauser спит все дольше и дольше, пока вы не вызовете reset (). Это сводит к минимуму задержку, когда вещи заняты.
На Code Review я получил предложение использовать класс Tailer из сообщества Apache. Глядя на его код, похоже, я понял правильную идею. Хотя Tailer немного более надежен, он использует ту же логику, что и мой код, он читает в цикле с задержкой Thread.sleep.
@AndrewHenle, я пишу интеграцию клавиатуры RGB для игры, и единственный способ получить информацию из нее (без очевидного взлома памяти) - это прочитать файлы журнала, которые мгновенно обновляются, как только в игре происходит событие. .
В настоящее время у вас нет конкретного вопроса. Таким образом, ваш пост будет лучше размещен на Проверка кода