有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java无法连续读取/监视远程文件

我使用JSCH尝试在一个不断更新的独立服务器上读取日志文件。我可以很好地提取文件中当前的任何内容,但一旦到达文件末尾,就会出现延迟,但不会提取新行,并且延迟打印语句会继续循环(我通过在程序旁边的日志上运行尾部来验证)。如果有人能指出我的代码中可能有错误或遗漏的地方,或者提出更好的方法,我将不胜感激

InputStream stream = sftpClient.get(filename);
BufferedReader br = new BufferedReader(new InputStreamReader(stream));
String line;
while (true)
{
    try
    {
        line = br.readLine();
        if (line == null)
        {
            System.out.println("End of file reached. Sleeping..");
            Thread.sleep(sleepTime);
            System.out.println("Retrying for more data..");
        }
        else
        {
            //do something with line, print for now.
            System.out.println(line);
        }
    }
    catch (Exception e)
    {
        System.out.println("Something went wrong: " + e);
    }
}

共 (4) 个答案

  1. # 1 楼答案

    为了补充crv提到的内容,下面是一个关于如何使用Apache Tailor的示例

    import java.io.File;
    
    import org.apache.commons.io.input.Tailer;
    import org.apache.commons.io.input.TailerListener;
    import org.apache.commons.io.input.TailerListenerAdapter;
    
    public class FileTailor {
    
        private static final int SLEEP = 500;
    
        public static void main(String[] args) throws Exception {
            FileTailor fileTailor = new FileTailor();
            fileTailor.run("log_file.log");
        }
    
        private void run(String path) throws InterruptedException {
            TailerListener listener = new LogFileListener();
            Tailer tailer = Tailer.create(new File(path), listener, SLEEP);
            tailer.run();
        }
    
        public class LogFileListener extends TailerListenerAdapter {
            @Override
            public void handle(String line) {
                //do something with line, print for now.
                System.out.println(line);
            }
        }
    }
    
  2. # 2 楼答案

    您可以看到Jsch的ChannelSftphere的源代码。获取远程文件时的InputStream returned by jsch在读取到远程文件末尾时设置一个标志。继续尝试从流中读取只会返回缓存的EOF指示

    Jsch有a ^{} method to retrieve information about a remote file,包括其大小和上次修改的时间戳。Jsch还有a version of the get method,它允许您跳过远程文件的第一部分。您可以定期调用stat()来检测文件是否已更改,然后使用get()跳过文件中已读取的部分,然后只读取新内容

    您可能还想考虑使用不同的SSH客户端库。SFTP protocol包含用于打开远程文件并读取或写入文件任意部分的低级命令。然而,Jsch并没有通过ChannelSftp公开此功能的全部范围。还有其他java SFTP客户端库提供对SFTP协议的低级访问

  3. # 4 楼答案

    我正在尝试这个,在我的例子中,我必须不断地读取日志,但我只能通过sftp访问它,正如@Kenster提到的,我通过调用stat()检查文件大小是否发生了变化,然后使用get( String src, String dst, SftpProgressMonitor monitor, int mode),它所做的是在我的目录中生成一个新文件,并且使用RESUME中的mode参数,它只接受最新的内容

    long remotepointer = 0;
    SftpATTRS atrr = null;
    Strinf remoteFile = "log.txt"
    Strinf tempFile = "/tmp/data/log.txt"
    while (true){
        try {  
          atrr =  channelSftp.stat(remoteFile);
          if(atrr.getSize() > remotepointer){
            remotepointer = atrr.getSize();
            channelSftp.get(remoteFile, tempFile,null,ChannelSftp.RESUME);
          }
        }catch (Exception e){
            System.out.println("Something went wrong: " + e);
        }
    }