objective-c – 从Unix命令读取NSTask / NSPipe

前端之家收集整理的这篇文章主要介绍了objective-c – 从Unix命令读取NSTask / NSPipe前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在编写一个 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,而([(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];

with 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];

解决方法

这是我通常如何做的一个工作示例:
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]){
        ...
    }   
}

猜你在找的C&C++相关文章