3

I put 'ON LINUX' in caps not to annoy you but because I have already been able to do this on Windows using 3 different file reading Classes. FileIntputStream BufferedReader RandomAccessFile (The last two I am sure of but the first could be wrong - my memory is baaad.) All of these are working perfectly on windows for me. My intended use of these readers is to read a text file line by line in real time, meaning, when a new version of this file is saved with a new line appended to it, the java program reads this line, does something with it and then continues checking for another new line.

I tried compiling using Java 7 openJDK, Java 7 Oracle, and Java 8 Oracle environments and all the resulting .jars worked fine on windows, and since Java is cross-platform I assumed they would work on Linux too (right?), yet every version I compile has failed when tested on linux. This was brought to my attention by a community forum member running linux Red Hat, no errors/exceptions, looked like it was running but just didn't work. I installed Ubuntu today and tried it for myself: The readers will read the original file fine but do not "stream" the file in real time. Changes to the file go unnoticed. I am very confused as to how this is possible and honestly I'm surprised it hasn't been brought up anywhere (as far as I can tell lol). Hopefully this means that I've made a stupid mistake somewhere in regards to ensuring linux compatibility that someone might track down. Any and all help/answers/workarounds are appreciated!

Here is an example of the code I am trying to implement into my program:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

public class Driver {

    public static void main(String[] args) {
        RandomAccessFile reader = null;
        try {
            reader = new RandomAccessFile(new File("/home/citats/csgo/console.log"), "r");
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        String currLine;
        Boolean done = false;
        while (!done) {
            try {
                if ((currLine = reader.readLine()) != null)
                {
                    System.out.println(currLine);
                    if (currLine.equals("done"))
                        done = true;
                } else
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        reader.close();
    }
}
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Citats
  • 31
  • 1
  • 2
  • Try using the newer NIO classes, as they might provide more direct access to the file. The older IO classes are probably using a Linux API that opens the file read-only, which might be accessing a snapshot of the file. (I guessing here). – Andreas Aug 17 '15 at 18:20
  • 1
    I had to add a `throws Exception` to `main` to take care of the missing `try-catch` around `reader.close`, I also changed your path to `/tmp/abc.log`. Then I did a `touch /tmp/abc.log` and run the program. Finally, I did an `echo test >>/tmp/abc.log`, and I did see the program producing the output. Can you provide instructions to reproduce the issue? – Roberto Attias Aug 17 '15 at 18:22
  • I also see the expected output both when echoing and when using nano to write to the file through the shell. However I don't see the output when I append a line to the log using gedit. Very strange. I think it is safe to assume that the game console that is writing to the log file likely suffers from the same problem that gedit is experiencing, whatever that may be! – Citats Aug 17 '15 at 19:31
  • If you do a "cat" of the file, do you see the new line, while not seeing it from your program? – Roberto Attias Aug 17 '15 at 19:52
  • That is correct Roberto. – Citats Aug 18 '15 at 03:19
  • same here , did u find any answer to your question ? did it worked with you ? – Ahmad Abu-Hamideh Oct 11 '16 at 07:03
  • Unfortunately not. In this case I abandoned trying to make a client side log reader with Java, learnt Sourcepawn, and wrote a server side plugin to do this. – Citats Oct 13 '16 at 17:18

1 Answers1

0

Tailing a file

To get functionality like tail -f where your solution is watching for new file updates then doing something with them see this answer: How can I follow a file like "Tail -f" does in Java without holding the file open (Prevent rename/delete). The source of this is informative for what you are attempting. I'm suspecting some of the seeks get around the issue you are seeing. Tailer Source

An alternative and quite interesting way to achieve similar results but with more power is with JavaRX-file where you can arrange for the new changes to be delivered in a more asychronous manner with Java NIO. There's an example on their main page: RxJava file github page

import com.github.davidmoten.rx.FileObservable;
import rx.Observable;
import java.io.File; 

Observable<String> items = 
     FileObservable.tailer()
               .file("/var/log/server.log")
               .startPosition(0)
               .sampleTimeMs(500)
               .chunkSize(8192)
               .utf8()
               .tailText();

RxJava

For more information about why use JavaRx see the RxJava project

Community
  • 1
  • 1
andygavin
  • 2,784
  • 22
  • 32