【问题标题】:Getting data from the nstask - communicating with command line - objective c从 nstask 获取数据 - 与命令行通信 - 目标 c
【发布时间】:2010-08-09 19:15:11
【问题描述】:

我知道如何向任务发送数据:

NSData *charlieSendData = [[charlieImputText stringValue] dataUsingEncoding:NSUTF8StringEncoding];
[[[task standardInput] fileHandleForWriting] writeData:charlieSendData];

但是我怎样才能得到任务的响应呢??

以利亚

【问题讨论】:

    标签: objective-c nsdata nstask


    【解决方案1】:

    NSPipeNSFileHandle 作为任务的standardOutput,并从中读取。

    NSTask * list = [[NSTask alloc] init];
    [list setLaunchPath:@"/bin/ls"];
    [list setCurrentDirectoryPath:@"/"];
    
    NSPipe * out = [NSPipe pipe];
    [list setStandardOutput:out];
    
    [list launch];
    [list waitUntilExit];
    [list release];
    
    NSFileHandle * read = [out fileHandleForReading];
    NSData * dataRead = [read readDataToEndOfFile];
    NSString * stringRead = [[[NSString alloc] initWithData:dataRead encoding:NSUTF8StringEncoding] autorelease];
    NSLog(@"output: %@", stringRead);
    

    请注意,如果您使用管道,则必须担心管道会被填满。如果您改为提供NSFileHandle,则任务可以输出它想要的所有内容,而不必担心丢失任何内容,但您也需要将数据写入磁盘的开销。

    【讨论】:

    • 我已经这样做了。 [task standardOutput] - 如果我只是调用它,它会给出输出吗?
    • @Elijah 默认情况下,没有。如果您想要输出,则必须在启动任务之前提供管道或文件句柄,然后开始从文件句柄(或[pipe fileHandleForReading])中读取数据以取回数据。 (它会给你NSData 对象,而不是字符串或任何东西)
    • 如何修改它以尽快获取数据而不是等待处理完成?
    • @4ntoine,查看this SO answer。您可以在从NSPipefileHandleForReading 返回的NSFileHandle 上调用waitForDataInBackgroundAndNotify。然后您可以使用NSNotificationCenter 收听NSFileHandleDataAvailableNotification
    【解决方案2】:

    Swift 3 解决方案,您可以实现一个接受 FileHandle 的闭包

    let process = Process()
    process.launchPath = launchPath
    process.arguments = arguments
    
    let stdOut = Pipe()
    process.standardOutput = stdOut
    let stdErr = Pipe()
    process.standardError = stdErr
    
    let handler =  { (file: FileHandle!) -> Void in
      let data = file.availableData
      guard let output = NSString(data: data, encoding: String.Encoding.utf8.rawValue)
        else { return}
    
      print(output.components(separatedBy: "\n").first!)
    }
    
    stdErr.fileHandleForReading.readabilityHandler = handler
    stdOut.fileHandleForReading.readabilityHandler = handler
    
    process.terminationHandler = { (task: Process?) -> () in
      stdErr.fileHandleForReading.readabilityHandler = nil
      stdOut.fileHandleForReading.readabilityHandler = nil
    }
    
    process.launch()
    process.waitUntilExit()
    

    【讨论】:

    • 值得注意的是,stdout/stdin 被缓冲,如果你的命令输出足够的数据,管道就会挂起,所以这个使用闭包的解决方案是你应该使用的解决方案。
    • @mxcl “足够”你的意思是“太多”,我猜?您的意思是,如果该工具可以输出比内存缓冲区容纳的更多的数据,那么它将阻塞,直到某个进程清空缓冲区?
    猜你喜欢
    • 1970-01-01
    • 2011-03-27
    • 2012-11-03
    • 2012-09-05
    • 1970-01-01
    • 1970-01-01
    • 2010-09-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多