• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag
 

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: NSTask with unzip
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: NSTask with unzip


  • Subject: Re: NSTask with unzip
  • From: Leonardo <email@hidden>
  • Date: Sun, 28 Nov 2010 23:51:17 +0100
  • Thread-topic: NSTask with unzip

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 <email@hidden>
> Data: Sun, 28 Nov 2010 08:52:33 -0500
> A: Leonardo <email@hidden>, Cocoa List <email@hidden>
> 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 <email@hidden>
>>> Data: Sat, 27 Nov 2010 12:12:39 -0500
>>> A: Dave DeLong <email@hidden>
>>> Cc: "gMail.com" <email@hidden>, Cocoa List
>>> <email@hidden>
>>> 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 <email@hidden>
>>>> 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 (email@hidden)
>>>>>
>>>>> 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:
>>>>>
>>>>> This email sent to email@hidden
>>>
>>
>>
>


_______________________________________________

Cocoa-dev mailing list (email@hidden)

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:

This email sent to email@hidden

  • Follow-Ups:
    • Re: NSTask with unzip
      • From: Tim Schröder <email@hidden>
    • Re: NSTask with unzip
      • From: Scott Ribe <email@hidden>
    • Re: NSTask with unzip
      • From: glenn andreas <email@hidden>
References: 
 >Re: NSTask with unzip (From: Ben Haller <email@hidden>)

  • Prev by Date: Re: OutlineView with big text editor [SOLVED]
  • Next by Date: Re: hidden file
  • Previous by thread: Re: NSTask with unzip
  • Next by thread: Re: NSTask with unzip
  • Index(es):
    • Date
    • Thread