Linux下的Java RandomAccessFile.java无法正常工作

我试图在java中实现简单的tail -f linux命令。 这是我的代码。

try { // position within the file File file = new File("/home/curuk/monitored/log.txt"); RandomAccessFile raFile = new RandomAccessFile(file, "r"); long last = file.lastModified(); // The last time the file was checked for changes long position = file.length(); while (true) { if (file.lastModified() > last) { last = file.lastModified(); readFromFile(raFile, (int) position, (int) (file.length() - position)); position = file.length(); } Thread.sleep(1000); } } catch (IOException e) { e.printStackTrace(); } private byte[] readFromFile(RandomAccessFile file, int position, int size) throws IOException { file.seek(position); byte[] bytes = new byte[size]; System.err.println(file.read(bytes, 0, size)); String s = new String(bytes); System.err.println(s); return bytes; } 

问题是,在Linux操作系统下, file.read(bytes, 0, size)总是返回-1,而在Windows下,同样的代码片段工作得很好(总是打印新行)。

编辑:

我通过添加raFile = new RandomAccessFile(file, "r");来解决这个问题raFile = new RandomAccessFile(file, "r"); 在每一次迭代。

 while (true) { raFile = new RandomAccessFile(file, "r"); if (file.lastModified() > last) { last = file.lastModified(); readFromFile(raFile, (int) position, (int) (file.length() - position)); position = file.length(); } Thread.sleep(1000); } 

不知道为什么,但现在在Linux下也能正常工作。 感谢你的努力人

这是一个完全基于Java 7的解决方案,使用新的WatchService基础架构:

作品,但相当粗糙…

 public final class Baz { public static void main(final String... args) throws IOException { // Get paths to the containing directory and the file we want to spy final Path dir = Paths.get("/tmp"); final Path file = dir.resolve("foo.txt"); // Get the watch service for our default filesystem // We are only interested in modifications and deletions final WatchService service = FileSystems.getDefault().newWatchService(); dir.register(service, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE); // Get a charset decoder -- we will be reading bytes from the file, // we will need to decode them to a string final CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder() .onMalformedInput(CodingErrorAction.IGNORE) .onUnmappableCharacter(CodingErrorAction.IGNORE); try ( // Open a SeekableByteChannel to the file -- read only final SeekableByteChannel channel = Files.newByteChannel(file, StandardOpenOption.READ); ) { long oldSize; while (true) { // Get the current size of our file oldSize = channel.size(); try { // Grab a key final WatchKey key = service.poll(1L, TimeUnit.SECONDS); if (key == null) // No events... continue; for (final WatchEvent<?> e: key.pollEvents()) { @SuppressWarnings("unchecked") final WatchEvent<Path> event = (WatchEvent<Path>) e; // What kind of event, to whom it applies final WatchEvent.Kind<Path> kind = event.kind(); final Path context = dir.resolve(event.context()); // If not to us, we don't care if (!context.equals(file)) continue; // If our file has disappeared, exit if (kind == StandardWatchEventKinds.ENTRY_DELETE) { System.err.println("File deleted"); System.exit(0); } // OK, so it's a modification, and it is our file: read the tail doRead(oldSize, decoder, channel); } // Reset the key for the next batch of events key.reset(); } catch (InterruptedException e) { // service.poll() interrupted: get out break; } } } } private static void doRead(final long oldSize, final CharsetDecoder decoder, final SeekableByteChannel channel) throws IOException { final long newSize = channel.size(); if (newSize <= oldSize) return; final int bufsize = (int) (newSize - oldSize); final ByteBuffer buf = ByteBuffer.allocate(bufsize); channel.position(oldSize).read(buf); buf.rewind(); decoder.reset(); System.out.println(decoder.decode(buf).toString()); } }