0

我使用 NSTask 运行 shell 命令并通过 NSPipe 输出数据。起初,我使用波纹管方法读取输出数据,没有任何问题。

- (void)outputAvailable:(NSNotification *)aNotification {
  NSString *newOutput;
  NSMutableData *allData = [[NSMutableData alloc] init];
  NSData *taskData = nil;        
  if((taskData = [readHandle availableData]) && [taskData length])
    newOutput = [[NSString alloc] initWithData:allData encoding:NSASCIIStringEncoding];
  NSLog(@"%@", newOutput);
  [readHandle readInBackgroundAndNotify];    
}

该方法的问题是它只输出 4096 字节的数据。所以我使用while循环来获取更多数据,修改方法如下:</p>

- (void)outputAvailable:(NSNotification *)aNotification {
  NSString *newOutput;
  NSMutableData *allData; //Added.
  NSData *taskData = nil;
  while ((taskData = [readHandle availableData]) && [taskData length]) {
    [allData appendData:taskData];
  }    
  newOutput = [[NSString alloc] initWithData:allData encoding:NSASCIIStringEncoding];
  NSLog(@"%@", newOutput);
  [readHandle readInBackgroundAndNotify];
}

那么问题就出现了:程序阻塞在while循环中,不能执行下面的语句。我确保这allData是我想要的,但是在附加最后一个数据块之后,它被阻塞了。你能给我一些解决方案吗?谢谢。

4

1 回答 1

0

您的while()循环有效地阻止了进一步的通知,导致整个程序阻塞等待刷新缓冲区的东西。

您应该readInBackgroundAndNotify,然后关闭availableBytes每个通知,将其附加到您的NSMutableData(可能保存在实例变量中)。当您处理通知时,不要尝试等待更多数据或执行任何类型的while循环。当有更多数据可用时,系统会通知您。

即系统将数据推送给您,您不会从系统中提取数据。


啊……好吧。您仍然应该仅在有可用数据时提取数据。你的while()循环正在这样做。咖啡不够。我的错。

最后一个块很可能是因为您的外部进程没有关闭管道;没有收到 EOF,因此,程序将永远等待更多永远不会到达的数据。

任何一个:

  • 确保后台任务退出

  • 检测您何时收到足够的数据并终止进程

如果您正在执行某种转换程序(例如tr),在该程序中将数据写入进程标准输入,那么您可能需要关闭标准输入管道。

于 2013-09-16T15:45:59.273 回答