我正在编写一个Cocoa应用程序,它需要执行UNIX程序并在生成时逐行读取其输出。我将NSTask和NSPipe设置为这样:
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来刷新数据吗?
编辑:使用-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];发布于 2012-11-15 17:13:26
以下是我通常如何做到这一点的一个工作示例:
task = [[NSTask alloc] init];
[task setLaunchPath:...];
NSArray *arguments;
arguments = ...;
[task setArguments:arguments];
NSPipe *outPipe;
outPipe = [NSPipe pipe];
[task setStandardOutput:outPipe];
outFile = [outPipe fileHandleForReading];
[outFile waitForDataInBackgroundAndNotify];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(commandNotification:)
name:NSFileHandleDataAvailableNotification
object:nil];
[task launch];
- (void)commandNotification:(NSNotification *)notification
{
NSData *data = nil;
while ((data = [self.outFile availableData]) && [data length]){
...
}
}发布于 2016-09-08 06:02:59
下面是获得任务输出的异步解决方案。
task.standardOutput = [NSPipe pipe];
[[task.standardOutput fileHandleForReading] setReadabilityHandler:^(NSFileHandle *file) {
NSData *data = [file availableData]; // this will read to EOF, so call only once
NSLog(@"Task output! %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
// if you're collecting the whole output of a task, you may store it on a property
//maybe you want to appenddata
//[weakself.taskOutput appendData:data];
}];希望能帮上忙。
https://stackoverflow.com/questions/13392271
复制相似问题