我有一些代码可以处理从我的应用程序导出数据。它接受一个充满 XML 的 NSString 并通过 PHP 脚本运行它来生成 HTMl、RTF 等。除非用户有一个很大的列表,否则它工作得很好。这显然是由于它超出了 NSPipe 8k 左右的缓冲区。
我在 readPipe 和 readHandle 中解决了这个问题(我认为),但我不确定如何在 writeHandle/writePipe 中处理它。应用程序将在 [writeHandle writeData:[in...
处进行沙滩球运动,除非我在 gdb 中中断它,等待几秒钟然后继续。
关于如何在我的代码中解决这个问题有什么帮助吗?
- (NSString *)outputFromExporter:(COExporter *)exporter input:(NSString *)input {
NSString *exportedString = nil;
NSString *path = [exporter path];
NSTask *task = [[NSTask alloc] init];
NSPipe *writePipe = [NSPipe pipe];
NSFileHandle *writeHandle = [writePipe fileHandleForWriting];
NSPipe *readPipe = [NSPipe pipe];
NSFileHandle *readHandle = [readPipe fileHandleForReading];
NSMutableData *outputData = [[NSMutableData alloc] init];
NSData *readData = nil;
// Set the launch path and I/O for the task
[task setLaunchPath:path];
[task setStandardInput:writePipe];
[task setStandardOutput:readPipe];
// Launch the exporter, it will convert the raw OPML into HTML, Plaintext, etc
[task launch];
// Write the raw OPML representation to the exporter's input stream
[writeHandle writeData:[input dataUsingEncoding:NSUTF8StringEncoding]];
[writeHandle closeFile];
while ((readData = [readHandle availableData]) && [readData length]) {
[outputData appendData:readData];
}
exportedString = [[NSString alloc] initWithData:outputData encoding:NSUTF8StringEncoding];
return exportedString;
}
最佳答案
自 10.7 起有一个新的 API,因此您可以避免使用 NSNotifications。
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
[self.taskOutput appendData:data];
}];
您可能想对 task.standardError
重复上面的操作。
重要:
当你的任务终止时,你必须将 readabilityHandler block 设置为 nil;否则,您将遇到 CPU 使用率过高的情况,因为读取永远不会停止。
[task setTerminationHandler:^(NSTask *task) {
// do your stuff on completion
[task.standardOutput fileHandleForReading].readabilityHandler = nil;
[task.standardError fileHandleForReading].readabilityHandler = nil;
}];
这都是异步的(您应该异步执行),因此您的方法应该有一个 ^completion block 。
关于cocoa - 解决传递大量数据时 NSFileHandle NSTask 阻塞的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1395273/