Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Cocoa NSTask/usr/bin/compress,循环写入standardInput,通过阻塞availableData读取standardOutput_Cocoa_Nstask - Fatal编程技术网

Cocoa NSTask/usr/bin/compress,循环写入standardInput,通过阻塞availableData读取standardOutput

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上阻塞,因为在数据到达之前我不能做任何事情,

我尝试使用/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
,等等。一旦你这样做了,你就可以将写入和读取从管道中分离出来,每个管道都可以按照自己的速度进行