Cocoa NSTask/usr/bin/compress,循环写入standardInput,通过阻塞availableData读取standardOutput
我尝试使用/usr/bin/compress压缩一个文件,启动时没有文件名,因此它从stdin获取数据并将压缩数据写入stdout。我使用标准输入、输出和错误的管道创建任务。在循环中,我从文件中读取一块数据,写入任务的stdin,然后使用[nsfilehandleavailabledata]从stdout读取。我试过2K、8K和12K的块大小。在所有情况下,我的程序都会挂起。我的目标是10.6 按照我的代码的结构,我更喜欢它在availableData上阻塞,因为在数据到达之前我不能做任何事情,调用方只希望在处理完成后返回。到目前为止,这一切都在主线中。一旦它工作,我将把这个部分移动到一个单独的线程,这样就不会阻塞主线程,是的,我将需要让调用者在从属线程退出后接受异步完成Cocoa NSTask/usr/bin/compress,循环写入standardInput,通过阻塞availableData读取standardOutput,cocoa,nstask,Cocoa,Nstask,我尝试使用/usr/bin/compress压缩一个文件,启动时没有文件名,因此它从stdin获取数据并将压缩数据写入stdout。我使用标准输入、输出和错误的管道创建任务。在循环中,我从文件中读取一块数据,写入任务的stdin,然后使用[nsfilehandleavailabledata]从stdout读取。我试过2K、8K和12K的块大小。在所有情况下,我的程序都会挂起。我的目标是10.6 按照我的代码的结构,我更喜欢它在availableData上阻塞,因为在数据到达之前我不能做任何事情,
init
{
self = [super init];
if (self) {
task = [[NSTask alloc] init];
NSPipe* stdin_Pipe = [NSPipe pipe];
NSPipe* stdoutPipe = [NSPipe pipe];
NSPipe* stderrPipe = [NSPipe pipe];
[task setStandardInput: stdin_Pipe];
[task setStandardOutput: stdoutPipe];
[task setStandardError: stderrPipe];
[task setLaunchPath: kCompressor];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver: self
selector: @selector (taskTerminated:)
name: NSTaskDidTerminateNotification
object: task];
[task launch];
}
return self;
}
写一些,读一些。没有说明compress何时决定写入
(NSData*) compressData: (NSData*) source
{
[[[task standardInput] fileHandleForWriting] writeData: source];
return [[[task standardOutput] fileHandleForReading] availableData];
}
。。。以及使用前面代码段的代码:
(BOOL) compressFile: (NSString*) file
{
//...
NSData* fileDataBlock = [sourceFileHandle readDataOfLength: kTargetFileReadBlockLen];
while ( [fileDataBlock length] > 0) {
NSData* compressedData = [origFileCompress compressData: currentBuffer];
//...
}
}
gdb显示我的程序正在执行此操作(首先是最新帧):
0x9a0ade5e在读$UNIX2003
0x91ebcc13位于_NSReadFromFileDescriptor中
0x91ec3c64 in-[NSConcreteFileHandle可用数据]
0x00002e8b in-[CompressCompressData:]在压缩时。m:266
当活动监视器-->示例进程显示/usr/bin/compress执行此操作时(最旧帧优先):
2672 fread(在libSystem.B.dylib中)+436[0x7fff8a0e501a]
2672 uu srefill1(在libSystem.B.dylib中)+27[0x7fff8a0e50a5]
2672_sread(在libSystem.B.dylib中)+19[0x7fff8a0dce34]
2672_uusread(在libSystem.B.dylib中)+16[0x7fff8a0e50ef]
2672 read$NOCANCEL(在libSystem.B.dylib中)+10[0x7fff8a095982]您无法控制压缩的工作方式—缓冲、输入与输出的关系等—因此向其写入一个块,然后读回一个块是不可能的 显然,您了解线程(您打算稍后将代码移出主线程),因此只需将数据写入另一个线程中的管道-您可以使用GCD计划并发块,启动
NSThread
,等等。一旦你这样做了,你就可以将写入和读取从管道中分离出来,每个管道都可以按照自己的速度进行