2011-01-12 100 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