Great! Thanks for the advises.
Now I have to zip and unzip a NSData (not a zip file) to a NSData.
In other words, I have to zip and unzip "data to data", without using any
file. Some idea?

-- Leonardo



> Da: Ben Haller <bhcocoa...@sticksoftware.com>
> Data: Sun, 28 Nov 2010 08:52:33 -0500
> A: Leonardo <mac.iphone....@gmail.com>, Cocoa List <cocoa-dev@lists.apple.com>
> Oggetto: Re: NSTask with unzip
> 
>   Yes, this looks good.  I like your category on NSFileHandle (not a
> subclass!); it's cleaner than the code at the link I sent you, since it
> doesn't just eat the error, and it's better as a category.
> 
>   Four things I would mention:
> 
> 1) Checking that the pipe could be created and actually has a file handle for
> reading would be a good idea; [NSPipe pipe] is documented as being allowed to
> return nil
> 
> 2) Checking -terminationStatus is a good idea once the task completes (after
> you're done pulling data out, you can then safely call -waitUntilExit on the
> task to be certain it has completed before calling -terminationStatus, AFAIK)
> 
> 3) You only use a pipe for standard out, not for standard in, but it's worth
> noting that a pipe for standard in needs to receive a -closeFile call or the
> file descriptor for that pipe doesn't get deleted correctly.  As a reminder to
> myself about this issue, I just send -closeFile to all of the pipes I'm using
> with a task, so that I don't forget to do it.  But your code is correct; I
> mention this just in case someone reading the archives adapts this code to a
> task that requires a standard in pipe.
> 
> 4) -launch can raise, so it is good to think about that; but as long as you're
> comfortable with your method raising, your code seems fine to me.
> 
>   Good stuff!  If anybody on the list knows whether the bug that the
> -availableDataOrError: hack circumvents has been fixed, and in what OS X
> release, I'd love to know that so I know whether it's safe to delete that
> rather unpleasant hack from my code.
> 
> Ben Haller
> McGill University
> 
> 
> On 2010-11-27, at 3:43 PM, Leonardo wrote:
> 
>> Ben, thank you so much! I have successfully done it.
>> I post the code here for anyone to use it. I love this list.
>> 
>> - (NSData*)UnzipFile:(NSString*)sourcePath
>> extractFileName:(NSString*)extractFileName
>> {    
>>    NSTask    *unzip = [[[NSTask alloc] init] autorelease];
>>    NSPipe    *aPipe = [NSPipe pipe];
>>    [unzip setStandardOutput:aPipe];
>>    [unzip setLaunchPath:@"/usr/bin/unzip"];
>>    [unzip setArguments:[NSArray arrayWithObjects:@"-p", sourcePath,
>> extractFileName, nil]];
>>    [unzip launch];
>> 
>>    NSMutableData    *dataOut = [NSMutableData data];
>>    NSData            *dataIn = nil;
>>    NSException        *error = nil;
>> 
>>    while((dataIn = [[aPipe fileHandleForReading]
>> availableDataOrError:&error]) && [dataIn length] && error == nil){
>>        [dataOut appendData:dataIn];
>>    }
>> 
>>    if([dataOut length] && error == nil){
>>        return dataOut;
>>    }
>> 
>>    return nil;
>> }
>> 
>> 
>> // Then I subclassed NSFileHandler this way
>> 
>> @implementation NSFileHandle (MyOwnAdditions)
>> - (NSData*)availableDataOrError:(NSException**)returnError
>> {
>>    for(;;){
>>        @try{
>>            return [self availableData];
>>        }...@catch (NSException *e) {
>>            if ([[e name] isEqualToString:NSFileHandleOperationException]) {
>>                if ([[e reason] isEqualToString:@"*** -[NSConcreteFileHandle
>> availableData]: Interrupted system call"]) {
>>                    continue;
>>                }
>>                if (returnError)
>>                    *returnError = e;
>>                return nil;
>>            }
>>            @throw;
>>        }
>>    }
>> }
>> @end
>> 
>> 
>>> Da: Ben Haller <bhcocoa...@sticksoftware.com>
>>> Data: Sat, 27 Nov 2010 12:12:39 -0500
>>> A: Dave DeLong <davedel...@me.com>
>>> Cc: "gMail.com" <mac.iphone....@gmail.com>, Cocoa List
>>> <cocoa-dev@lists.apple.com>
>>> Oggetto: Re: NSTask with unzip
>>> 
>>>  Here's a post that I found useful:
>>> 
>>> http://dev.notoptimal.net/2007/04/nstasks-nspipes-and-deadlocks-when.html
>>> 
>>>  Dave, not sure what you mean here.  NSPipe uses NSFileHandle.  Does using
>>> an
>>> NSFileHandle directly change things somehow?  If so, why?  I think this is
>>> an
>>> avenue I haven't explored; once I (finally) figured out the right magic
>>> incantations to get things to work reliably with NSPipe, I now recycle that
>>> code everywhere I need an NSTask :->.
>>> 
>>> Ben Haller
>>> McGill University
>>> 
>>> 
>>> On 2010-11-27, at 11:48 AM, Dave DeLong wrote:
>>> 
>>>> The way I get around this is to use an NSFileHandle for standard out
>>>> instead
>>>> of an NSPipe. It's a bit less efficient, but slightly more convenient.
>>>> 
>>>> Dave
>>>> 
>>>> Sent from my iPhone
>>>> 
>>>> On Nov 27, 2010, at 7:59 AM, Ben Haller <bhcocoa...@sticksoftware.com>
>>>> wrote:
>>>> 
>>>>> On 2010-11-26, at 7:33 AM, gMail.com wrote:
>>>>> 
>>>>>> Hi, I can properly unzip a zip file launching a NSTask with
>>>>>> /usr/bin/unzip
>>>>>> The task saves the unzipped file to the disk, then a I read the unzipped
>>>>>> file in a NSData. Well. My question is:
>>>>>> Can I do the same job without saving the unzipped file to the disk?
>>>>>> 
>>>>>> I have tried to set the standard output to a pipe - which works well with
>>>>>> other tasks - but here it doesn't work. The task never exits. Here's the
>>>>>> wrong code:
>>>>>> 
>>>>>> NSTask *unzip = [[[NSTask alloc] init] autorelease];
>>>>>> [unzip setLaunchPath:@"/usr/bin/unzip"];
>>>>>> [unzip setArguments:[NSArray arrayWithObjects:@"-p", zipfile,
>>>>>> @"filetounzip", nil]];
>>>>>> 
>>>>>> NSPipe *aPipe = [NSPipe pipe];
>>>>>> [unzip setStandardOutput:aPipe];
>>>>>> [unzip launch];
>>>>>> [unzip waitUntilExit];
>>>>>> 
>>>>>> if([unzip terminationStatus] == noErr){
>>>>>>  dictData = [NSMutableData data];
>>>>>>  while((dataOut = [aPipe availableData]) && [dataOut length]){
>>>>>>      [dictData appendData:dataOut];
>>>>>>  }
>>>>>> }
>>>>> 
>>>>> If I recall correctly, the problem is likely to be your use of
>>>>> -waitUntilExit.  That API should apparently have a large red label on it
>>>>> ("Warnin', lark's vomit!") since everybody wants to use it this way.  The
>>>>> problem is that the task's output pipe fills up because it isn't being
>>>>> serviced, and then things get locked up.  You need to go with asynchronous
>>>>> reads to service the pipe as output gets stuffed into it.  There should be
>>>>> lots of examples of this on this list, now that you know what to look for.
>>>>> 
>>>>> What would be great would be a new call, along the lines of
>>>>> -dataFromWaitingUntilExit or some such, that does all this for you, since
>>>>> this is so commonly what people want to do.
>>>>> 
>>>>> Ben Haller
>>>>> McGill University
>>>>> 
>>>>> _______________________________________________
>>>>> 
>>>>> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
>>>>> 
>>>>> Please do not post admin requests or moderator comments to the list.
>>>>> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>>>>> 
>>>>> Help/Unsubscribe/Update your Subscription:
>>>>> http://lists.apple.com/mailman/options/cocoa-dev/davedelong%40me.com
>>>>> 
>>>>> This email sent to davedel...@me.com
>>> 
>> 
>> 
> 


_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to