【问题标题】:Java RandomAccessFile.java under linux not working correctlylinux下Java RandomAccessFile.java不能正常工作
【发布时间】:2014-03-18 16:25:11
【问题描述】:

我正在尝试在 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 下,相同的 sn-p 代码工作得很好(总是打印新行)。

编辑:

我通过在每次迭代中添加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 linux tail randomaccessfile


    【解决方案1】:

    这是一个完全基于 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());
        }
    }
    

    【讨论】:

    • 感谢您的回答,但我们不使用 Java 7
    • 您知道 Java 8 从昨天开始就发布了吗? ;)
    • Feb 2013 之后 Java 6 就不再支持了?
    猜你喜欢
    • 2019-03-07
    • 1970-01-01
    • 2012-01-08
    • 1970-01-01
    • 1970-01-01
    • 2021-06-28
    • 1970-01-01
    • 2020-04-18
    • 2012-06-12
    相关资源
    最近更新 更多