RandomAccessFile.seek() не работает в Linux

Я использую какую-то реализацию tail -f, чтобы отслеживать изменения в файле (почти как это ). Для этого я использую RandomAccessFile, периодически проверяю, не увеличилась ли длина файла и если да, то ищу и считываю новые строки (все происходит в отдельном потоке FileTailer).

Теперь все работает, как и ожидалось, в Windows, но я протестировал свою программу в Linux, и она не работает должным образом. Вот метод run() класса FileTailer. В частности, в linux происходит сбой в той части, где вызывается file.seek(filePointer), а затем вызывается file.readLine(), из которых последний неожиданно возвращает NULL (хотя filePointer правильно увеличивается, если я добавляю содержимое в файл, получая хвост в время выполнения).

public void run() {
// The file pointer keeps track of where we are in the file
long filePointer = 0;

// Determine start point
if(startAtBeginning){
  filePointer = 0;
}
else {
  filePointer = logfile.length();
}

try {
  // Start tailing
  tailing = true;
  RandomAccessFile file = new RandomAccessFile(logfile, "r");
  while(tailing) {
      // Compare the length of the file to the file pointer
      long fileLength = logfile.length();
      System.out.println("filePointer = " + filePointer + " | fileLength = " + fileLength);
      if(fileLength < filePointer) {
        // Log file must have been rotated or deleted; 
        // reopen the file and reset the file pointer
        file = new RandomAccessFile(logfile, "r");
        filePointer = 0;
      }

      if(fileLength > filePointer) {
        // There is data to read
        file.seek(filePointer);
        String line = file.readLine();
        System.out.println("new line = " + line);
        while(line != null){
          if(!line.isEmpty())
            try {
                fireNewFileLine(line);
            } catch (ParseException e) {
                e.printStackTrace();
            }
          line = file.readLine();
        }
        filePointer = file.getFilePointer();
      }
      // Sleep for the specified interval
      sleep(sampleInterval);

  }

  // Close the file that we are tailing
  file.close();
}
catch(InterruptedException | IOException e){
  e.printStackTrace();
}
}

Как я уже сказал, в Windows все работает как надо, но в Linux строковая переменная «line» имеет значение NULL после того, как она должна была быть заполнена новой добавленной строкой, поэтому fireNewLine вызывается на NULL, и все идет к чертям.

Кто-нибудь знает, почему это происходит в системах Linux?


person Akustiker    schedule 22.06.2017    source источник
comment
Здесь нет доказательств того, что проблема seek(), но я не знаю, почему вы вообще звоните seek(). Вам не нужно. Вы всегда должны располагаться в конце файла. Ничто не изменит вашу позицию в файле, кроме ваших собственных readLine() вызовов.   -  person user207421    schedule 22.06.2017
comment
И на самом деле вам RandomAccessFile вообще не нужно. Используйте BufferedReader и просто спите, пока readLine() возвращает значение null.   -  person user207421    schedule 22.06.2017


Ответы (1)


Вам не нужно все это, или RandomAccessFile. Вы всегда находитесь в конце файла. Все, что вам нужно, это:

public void run() {

    try {
      // Start tailing
      tailing = true;
      BufferedReader reader = new BufferedReader(new FileReader(logfile));
      String line;
      while (tailing) {
          while ((line = reader.readLine() != null) {
              System.out.println("new line = " + line);
              if(!line.isEmpty()) {
                  try {
                      fireNewFileLine(line);
                  } catch (ParseException e) {
                      e.printStackTrace();
                  }
              }
          }
          // Sleep for the specified interval
          sleep(sampleInterval);
        }
        // Close the file that we are tailing
        reader.close();
    } catch(InterruptedException | IOException e) {
        e.printStackTrace();
    }
}

с, возможно, некоторым положением для повторного открытия файла.

Э&ОЕ

person user207421    schedule 23.06.2017