2011-01-12 103 views
3

我需要实时读取日志文件的最后一行,并捕获要添加的行。如何使用NSTask获得类似于Tail -f的内容

类似于尾巴-f的东西。

因此,我第一次尝试使用Nfask使用Tail -f。

使用下面的代码,我看不到任何输出:

NSTask *server = [[NSTask alloc] init]; 
    [server setLaunchPath:@"/usr/bin/tail"]; 
    [server setArguments:[NSArray arrayWithObjects:@"-f", @"/path/to/my/LogFile.txt",nil]]; 

    NSPipe *outputPipe = [NSPipe pipe]; 
    [server setStandardInput:[NSPipe pipe]]; 
    [server setStandardOutput:outputPipe]; 

    [server launch]; 
    [server waitUntilExit]; 
    [server release]; 

    NSData *outputData = [[outputPipe fileHandleForReading] readDataToEndOfFile]; 
    NSString *outputString = [[[NSString alloc] initWithData:outputData encoding:NSUTF8StringEncoding] autorelease]; 
    NSLog (@"Output \n%@", outputString); 

我可以看到输出如预期使用时:

[server setLaunchPath:@"/bin/ls"]; 
  1. 我如何能捕捉的输出那尾巴NSTask?

  2. 是否有任何替代方法,我可以打开一个流到文件,每次添加一行,输出到屏幕上? (基本日志记录功能)

回答

4

这是一个有点棘手做自己的方式,为readDataToEndOfFile会等到tail返回前关闭输出流,但tail -f永远不会关闭输出流(标准输出)。然而,这对于基本的C I/O代码来说实际上很简单,所以我掀起了一个简单的FileTailer类,你可以检查。这不是什么幻想,但它应该告诉你它是如何完成的。这里是FileTailer.h,FileTailer.mtest driver的来源。

这堂课的肉很简单。您将它传递给一个块,并从流中读取一个字符(如果可能)并将其传递给该块;如果已经到达EOF,则等待几秒(由refresh确定),然后尝试再次读取流。

- (void)readIndefinitely:(void (^)(int ch))action 
{ 
    long pos = 0L; 
    int ch = 0; 

    while (1) { 
     fseek(in, pos, SEEK_SET); 
     int ch = fgetc(in); 
     pos = ftell(in); 
     if (ch != EOF) { 
      action(ch); 
     } else { 
      [NSThread sleepForTimeInterval:refresh]; 
     } 
    } 
} 

你可以把它倒也干脆,就像这样:

FileTailer *tail = [[[FileTailer alloc] initWithStream:stdin refreshPeriod:3.0] autorelease]; 
[tail readIndefinitely:^ void (int ch) { printf("%c", ch); }]; 

(警告:我写的FileTailer类非常快,所以它现在有点难看,应该清理了一下,但它应作为对如何无限期地读取文件的体面的例子,点菜tail -f

+0

是否有必要呼吁每一个`fseek`通过循环?即使在`fgetc`返回`EOF`之后,是否有必要调用它? – benzado 2011-01-12 23:14:41

1

下面是Objective-C中使用“尾-f日志文件”通过NSTask方式:

asynctask.m - 即显示如何实现异步标准输入,用于与NSTask

处理数据的stdout & stderr流的示例代码...

作为一个GUI的较少的应用(即一个基于基础的命令行工具),asynctask.m手动运行NSRunLoop 以启用异步“waitForDataInBackgroundAndNotify”通知。此外,asynctask.m 使用pthread_create(3)和pthread_detach(3)将超过64 KB写入NSTask的stdin。在可用asynctask.m的

的源代码:http://www.cocoadev.com/index.pl?NSPipe