我正在編寫一個Cocoa應用程序,它需要執行一個UNIX程序並逐行讀取它的輸出,因爲它們是在生成的。我成立了一個NSTask和NSPipe這樣:NSTask/NSPipe從Unix命令中讀取
task = [[NSTask alloc] init];
pipe = [NSPipe pipe];
[task setStandardOutput:pipe];
//... later ...
[task setArguments:...];
[task setLaunchPath:@"..."];
[task launch];
handle = [[task fileHandleForReading] retain];
的命令不會終止,直到程序告訴它與[task terminate]
這樣做。我已經嘗試了幾種從句柄中讀取的方法,例如-readInBackgroundAndNotify
,while([(data = [handle availableData]) length] > 0)
和-waitForDataInBackgroundAndNotify
,但是管道似乎不會產生任何數據。有什麼方法可以「戳」NSTask
或NSPipe
以刷新數據?
EDIT:與-readInBackgroundAndNotify
:
[handle readInBackgroundAndNotify];
notification_block_t handlerBlock =
^(NSNotification *notification) {
NSData *data = [[notification userInfo]
objectForKey: NSFileHandleNotificationDataItem];
/*... do stuff ...*/
[self addNotification: handle block: handlerBlock];
};
[self addNotification: handler block: handlerBlock];
//...
- (void)addNotification:(id)handle block:(notification_block_t)block {
[[NSNotificationCenter defaultCenter]
addObserverForName: NSFileHandleReadCompletionNotification
object: handle
queue: [NSOperationQueue mainQueue]
usingBlock: block];
}
與-waitForDataInBackgroundAndNotify
:
[handle waitForDataInBackgroundAndNotify];
notification_block_t handlerBlock =
^(NSNotification *notification) {
NSData *data = [handle availableData];
/*... do stuff ...*/
};
[self addNotification: handler block: handlerBlock];
與while
循環:
[self startProcessingThread: handle];
//...
- (void)startProcessingThread:(NSFileHandle *)handle {
[[NSOperationQueue mainQueue]
addOperation: [[[NSInvocationOperation alloc]
initWithTarget: self
selector: @selector(dataLoop:)
object: handle] autorelease]];
}
- (void)dataLoop:(NSFileHandle *)handle {
NSData *data;
while([(data = [handle availableData]) length] > 0) {
/*... do stuff ...*/
}
}
編輯2:該參數設置如下(該命令tshark
):
NSArray *cmd = [NSArray arrayWithObjects:@"-R", @"http.request",
@"-Tfields", @"-Eseparator='|'",
@"-ehttp.host", @"-ehttp.request.method",
@"-ehttp.request.uri", nil];
cmd = [[cmd arrayByAddingObjectsFromArray:[self.ports map:^(id arg1, NSUInteger idx) {
return [NSString stringWithFormat:@"-d tcp.port==%d,http", [arg1 intValue]];
}]]
arrayByAddingObject:[@"dst " stringByAppendingString:
[self.hosts componentsJoinedByString:@" or dst "]]];
[self.tsharktask setArguments:cmd];
發佈您的所有代碼(例如您如何定義NSFileHandleDataAvailableNotification)。 –
'typedef(^ notification_block_t)(NSNotification *);',當然。 – Actorclavilis