Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何检查正在使用java进行外部更新的文件的内容?_Java_File Io_Process - Fatal编程技术网

如何检查正在使用java进行外部更新的文件的内容?

如何检查正在使用java进行外部更新的文件的内容?,java,file-io,process,Java,File Io,Process,有一个shell脚本正在更新日志文件 我想在日志文件写入时逐行显示日志(而不是一次显示整个文件) 写入文件工作正常,但我在读取文件时遇到问题,因为它一次显示整个文件 以下是我的阅读代码: String nmapstatusfile = runMT.instdir+"/logs/nmapout."+customer+".log"; String nmapcommand=runMT.instdir+"/bin/doscan.sh "+nmapoutfile+" " +IPRange+" "+

有一个shell脚本正在更新日志文件

我想在日志文件写入时逐行显示日志(而不是一次显示整个文件)

写入文件工作正常,但我在读取文件时遇到问题,因为它一次显示整个文件

以下是我的阅读代码:

String nmapstatusfile = runMT.instdir+"/logs/nmapout."+customer+".log";
String nmapcommand=runMT.instdir+"/bin/doscan.sh "+nmapoutfile+" "
    +IPRange+" "+nmapstatusfile+" "+nmapdonefile;

System.out.println("nmapcommand is .. "+nmapcommand);
Runtime r = Runtime.getRuntime();
Process pr = r.exec(nmapcommand);
RandomAccessFile raf =null;
try {
    System.out.println(nmapstatusfile);
    System.out.println("Reading a file");
raf = new RandomAccessFile(nmapstatusfile, "r");            
} catch (FileNotFoundException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
} // read from input file
System.out.println("Will print file contents line by line...");
long pos = 0;
raf.seek(pos);
String line =null;
while ((line = raf.readLine())!= null) {
    System.out.println("in while loop for file read.");
    System.out.println(line);
}
pos = raf.getFilePointer();
pr.waitFor();   
我使用了RandomAccessFile,但无法获得所需的结果

如何读取文件内容以便逐行显示

public static void main(String[] args) throws IOException {
    FileWriter fw = new FileWriter(new File("C://test.txt"));
    BufferedWriter bw = new BufferedWriter(fw);
    bw.append("Hi");
    //bw.close();
    FileReader fr = new FileReader(new File("C://test.txt"));
    BufferedReader br = new BufferedReader(fr);
    System.out.println(br.readLine());
}

OP : null
if you uncomment bw.close() , then OP : Hi..

所以,问题是每次脚本写入日志文件时,都需要保存该文件,需要通知()等待的线程,并在控制台上显示它

您可以为读卡器实现轮询策略,以避免从写卡器向读卡器发送额外通知
下面是一个简单的工作示例:

  • Writer从主线程更新日志文件(通过控制台的用户输入)
  • 读卡器定期轮询
    日志文件
    ,并输出一行


当多个读写器在不同的线程/进程中运行时,您可能需要添加额外的文件锁定和一致性检查。

这需要Java 7,因为它在文件系统上注册了一个监视程序,当给定文件发生更改时,将通知该监视程序。它允许任意数量的读卡器(使用同步来避免竞争条件)


所以你的意思是说如果你的脚本在文件中写了一行,你的程序必须在控制台上显示它???看看这个。可能重复我不知道你为什么坚持在这里使用递归。这真的是问题的一部分吗?@KickButtowski,因为我认为实际的问题是关于IO操作,而不是算法(无论是递归还是简单迭代)。unix和windows下的文件系统语义不同。我很确定OP正在使用unix(“.sh”文件终止),而您似乎正在使用windows。@tucuxi-是的。。他正在使用shell脚本:)。。。这将如何改变OP在读取日志文件之前必须保存日志文件的事实(我相信他希望逐行读取)。。我只是指出他可能面临的问题。。。他已经开始写shell脚本了。。它正在异步运行。。。现在,他怎么知道什么时候该读书??。。他无法控制写入日志文件的数据。如果我错了,请纠正我。。。。脚本只有在完成将所有内容写入文件时才会关闭该文件。在windows中,读取尚未关闭的文件通常是错误的。在unix中,这样做是非常典型的,根本不是错误。OP试图用unix的方式做事情(本质上实现了一种“tail-f”)。噢。。正在重定向O/P。。。看起来很公平。。。但他说“我希望递归地显示日志文件中的日志。这意味着当脚本在日志文件中写入时,我希望读取文件的内容并逐行显示”。。他不希望流/重定向O/P。。。他想直接从日志文件中读取。。当它被其他线程写入时,如何能够读取它???请参见下面我的答案。在linux下工作正常-在一个控制台上附加到文件,请参阅正在运行的程序显示更改。
public class Test {
    public static void main(String[] args) throws IOException {

        // async log reader based on timerTask
        LogReader logReader = new LogReader("test.txt");
        logReader.start(); // starts polling log file in Timer thread

        // main thread simulating writes to file from user input
        BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter logWriter = new BufferedWriter(new FileWriter(new File("test.txt")));
        String line = null;
        while (!(line = console.readLine()).equals("end")) {
            logWriter.write(line);
            logWriter.newLine();
            logWriter.flush();
        }
        logReader.stop();
        logWriter.close();
    }

    /**
     * reads file from separate thread
     */
    static class LogReader {
        File mLogFile = null;
        BufferedReader mReader = null;
        TimerTask mCheckFileTask = null;

        LogReader(String logFile) throws FileNotFoundException {
            mLogFile = new File(logFile);
            mReader = new BufferedReader(new FileReader(mLogFile));
        }

        /**
         * launches checking thread and output thread
         */
        void start() {
            mCheckFileTask = new TimerTask() {
                @Override
                public void run() {
                    // possibly some extra checks :
                    // file size or lastModified() time changed since last time
                    try {
                        writeChange();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                        throw new Error(e1);
                    }
               }
            };

            new Timer().schedule(mCheckFileTask, 500, 500);
        }

        private void writeChange() throws IOException {
            String line;
            line = mReader.readLine();
            if (line != null) {
                System.out.println("line added: " + line);
            }
        }

        void stop() throws IOException {
            System.out.println("stopping reader");
            mCheckFileTask.cancel();
            mReader.close();
        }
    }
}
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.ClosedWatchServiceException;
import java.nio.file.Path;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.ArrayDeque;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Reads lines from a file that is actively being updated by another process
 */
public class Tailer {
    private static final Logger logger = Logger.getLogger("Tailer");

    private long tooLateTime = -1;
    private final long maxMsToWait;
    private final File file;
    private long offset = 0;
    private int lineCount = 0;
    private boolean ended = false;
    private WatchService watchService = null; 
    ArrayDeque<String> lines = new ArrayDeque<>();

    /**
     * Allows output of a file that is being updated by another process.
     * @param file to watch and read
     * @param maxTimeToWaitInSeconds max timeout; after this long without changes,
     * watching will stop. If =0, watch will continue until <code>stop()</code>
     * is called.
     */
    public Tailer(File file, long maxTimeToWaitInSeconds) {
        this.file = file;
        this.maxMsToWait = maxTimeToWaitInSeconds * 1000;
    }

    /**
     * Start watch.
     */
    public void start() {
        updateOffset();
        // listens for FS events
        new Thread(new FileWatcher()).start();  
        if (maxMsToWait != 0) {
            // kills FS event listener after timeout
            new Thread(new WatchDog()).start();
        }     
    }

    /**
     * Stop watch.
     */
    public void stop() {
        if (watchService != null) {
            try {
                watchService.close();
            } catch (IOException ex) {
                logger.info("Error closing watch service");
            }
            watchService = null;
        }
    }

    private synchronized void updateOffset() {
        tooLateTime = System.currentTimeMillis() + maxMsToWait;
        try {
            BufferedReader br = new BufferedReader(new FileReader(file));
            br.skip(offset);            
            while (true) {
                String line = br.readLine();
                if (line != null) {
                    lines.push(line);
                    // this may need tweaking if >1 line terminator char
                    offset += line.length() + 1; 
                } else {
                    break;
                }
            }
            br.close();
        } catch (Exception ex) {
            logger.log(Level.SEVERE, "Error reading", ex);
        }        
    }

    /**
     * @return true if lines are available to read
     */
    public boolean linesAvailable() {
        return ! lines.isEmpty();
    }

    /**
     * @return next unread line
     */
    public synchronized String getLine() {
        if (lines.isEmpty()) {
            return null;
        } else {
            lineCount ++;
            return lines.removeLast();
        }
    }

    /**
     * @return true if no more lines will ever be available, 
     * because stop() has been called or the timeout has expired
     */
    public boolean hasEnded() {
        return ended;
    }

    /**
     * @return next line that will be returned; zero-based
     */
    public int getLineNumber() {
        return lineCount;
    }

    private class WatchDog implements Runnable {
        @Override
        public void run() {
            while (System.currentTimeMillis() < tooLateTime) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                    // do nothing
                }
            }
            stop();
        }
    }

    private class FileWatcher implements Runnable {
        private final Path path = file.toPath().getParent();
        @Override
        public void run() {
            try {
                watchService = path.getFileSystem().newWatchService();
                path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
                while (true) {
                    WatchKey watchKey = watchService.take();
                    if ( ! watchKey.reset()) {
                        stop();
                        break;
                    } else if (! watchKey.pollEvents().isEmpty()) {
                        updateOffset();
                    }
                    Thread.sleep(500);
                }
            } catch (InterruptedException ex) {
                logger.info("Tail interrupted");
            } catch (IOException ex) {
                logger.log(Level.WARNING, "Tail failed", ex);
            } catch (ClosedWatchServiceException ex) {
                // no warning required - this was a call to stop()
            }
            ended = true;
        }
    }

    /**
     * Example main. Beware: the watch listens on a whole folder, not on a single
     * file. Any update on a file within the folder will trigger a read-update.
     * @param args
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {
        String fn = args.length == 0 ? "/tmp/test/log.txt" : args[0];
        Tailer t = new Tailer(new File(fn), 10);
        t.start();
        while ( ! t.hasEnded()) {
            while (t.linesAvailable()) {
                System.out.println(t.getLineNumber() + ": " + t.getLine());
            }
            Thread.sleep(500);
        }
    }
}