2011-01-12 13 views
3

Ich muss die letzte Zeile zu einer Log-Datei in Echtzeit lesen, und erfassen Sie diese Zeile hinzugefügt werden.Wie bekomme ich etwas ähnlich wie Tail -f mit NSTask

Ähnlich wie Tail -f.

Also war mein erster Versuch, Tail-f mit NSTask zu verwenden.

ich jeden Ausgang nicht sehen kann den Code mit unter:

[server setLaunchPath:@"/bin/ls"]; 
  1. Wie ich die Ausgabe erfassen kann:

    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); 
    

    ich die Ausgabe wie erwartet sehen kann bei der Verwendung von dieser Schwanz NSTask?

  2. Gibt es eine Alternative zu dieser Methode, wo ich einen Stream zu Datei öffnen kann und jedes Mal, wenn eine Zeile hinzugefügt wird, es auf dem Bildschirm ausgeben? (Grund Logging-Funktionalität)

Antwort

4

Dies ist ein wenig schwierig Weg zu tun, wie readDataToEndOfFile warten, bis tail den Ausgangsstrom schließt vor der Rückkehr, aber tail -f schließt nie den Ausgangsstrom (stdout). Dies ist jedoch ziemlich einfach mit grundlegenden C-I/O-Code zu tun, also habe ich eine einfache FileTailer Klasse ausgepeitscht, die Sie auschecken können. Es ist nichts Besonderes, aber es sollte dir zeigen, wie es gemacht wird. Hier sind die Quellen für FileTailer.h, FileTailer.m, und eine test driver.

Das Fleisch der Klasse ist ziemlich einfach. Sie übergeben ihm einen Block und er liest (wenn möglich) ein Zeichen aus dem Stream und übergibt es an den Block. Wenn EOF erreicht wurde, wartet es einige Sekunden (bestimmt durch refresh) und versucht dann, den Stream erneut zu lesen.

- (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]; 
     } 
    } 
} 

Sie können es nennen ziemlich einfach, wie folgt aus:

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

(Caveat: Ich schrieb die FileTailer Klasse ziemlich schnell, so ist es irgendwie hässlich jetzt und sollte ein wenig gereinigt werden , aber es sollte als ein anständiges Beispiel dienen, wie eine Datei auf unbestimmte Zeit zu lesen, à la tail -f)

+0

Ist es notwendig, auf jeden zu nennen 'fseek' durch die Schleife? Ist es notwendig, es aufzurufen, nachdem 'fgetc'' EOF' zurückgibt? – benzado

+0

Funktioniert gut, ich musste es nur auf einem anderen Thread ausführen, um den Hauptthread nicht zu blockieren. Danke, dass du dir die Zeit genommen hast, um die Lösung zu schreiben. Ich schätze das wirklich! – Bach

+0

@benzado: Streng genommen, nein. Sie können den 'ftell'-Aufruf direkt vor dem Schlafen in den Thread verschieben und dann erst nach dem Aufwachen 'fseek' aufrufen. Dieser Code ist ein wenig vereinfacht. – mipadi

1

Hier ist ein Weg, „tail -f Logfile“ über NSTask in Objective-C zu verwenden.

asynctask.m - Beispielcode, der zeigt, wie asynchronen stdin, stdout & Stderr Ströme zur Verarbeitung von Daten mit NSTask

...

Als eine GUI-Anwendung implementieren weniger (d.h. ein Foundation-basiertes Befehlszeilen-Tool), führt asynctask.m einen NSRunLoop manuell aus, um die Verwendung asynchroner "waitForDataInBackgroundAndNotify" -Benachrichtigungen zu ermöglichen. Darüber hinaus verwendet asynctask.m pthread_create (3) und pthread_detach (3) zum Schreiben von mehr als 64 KB in die Standardeingabe einer NSTask.

Quellcode von asynctask.m unter: http://www.cocoadev.com/index.pl?NSPipe

Verwandte Themen