Java: opening and reading from a file without locking it

前端 未结 4 791
盖世英雄少女心
盖世英雄少女心 2020-12-16 17:42

I need to be able to mimic \'tail -f\' with Java. I\'m trying to read a log file as it\'s being written by another process, but when I open the file to read it, it locks the

4条回答
  •  猫巷女王i
    2020-12-16 18:37

    java.io gives you a mandatory file lock and java.nio gives you an advisory file lock

    If you want to read any file without any lock you can use below classes

    import java.nio.channels.FileChannel;
    import java.nio.file.Paths;
    

    If you want to tail a file line by line use below code for the same

    public void tail(String logPath){
        String logStr = null;
        FileChannel fc = null;
        try {
            fc = FileChannel.open(Paths.get(logPath), StandardOpenOption.READ);
            fc.position(fc.size());
        } catch (FileNotFoundException e1) {
            System.out.println("FileNotFoundException occurred in Thread : " + Thread.currentThread().getName());
            return;
        } catch (IOException e) {
            System.out.println("IOException occurred while opening FileChannel in Thread : " + Thread.currentThread().getName());
        }
        while (true) {
            try {
                logStr = readLine(fc);
                if (logStr != null) {
                    System.out.println(logStr);
                } else {
                    Thread.sleep(1000);
                }
            } catch (IOException|InterruptedException e) {
                System.out.println("Exception occurred in Thread : " + Thread.currentThread().getName());
                try {
                    fc.close();
                } catch (IOException e1) {
                }
                break;
            }
        }
    }
    
    private String readLine(FileChannel fc) throws IOException {
        ByteBuffer buffers = ByteBuffer.allocate(128);
        // Standard size of a line assumed to be 128 bytes
        long lastPos = fc.position();
        if (fc.read(buffers) > 0) {
            byte[] data = buffers.array();
            boolean foundTmpTerminator = false;
            boolean foundTerminator = false;
            long endPosition = 0;
            for (byte nextByte : data) {
                endPosition++;
                switch (nextByte) {
                case -1:
                    foundTerminator = true;
                    break;
                case (byte) '\r':
                    foundTmpTerminator = true;
                    break;
                case (byte) '\n':
                    foundTmpTerminator = true;
                    break;
                default:
                    if (foundTmpTerminator) {
                        endPosition--;
                        foundTerminator = true;
                    }
                }
                if (foundTerminator) {
                    break;
                }
            }
            fc.position(lastPos + endPosition);
            if (foundTerminator) {
                return new String(data, 0, (int) endPosition);
            } else {
                return new String(data, 0, (int) endPosition) + readLine(fc);
            }
        }
        return null;
    }
    

提交回复
热议问题