• 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: Sat, 27 Nov 2010 21:43:55 +0100
  • Thread-topic: NSTask with unzip

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: Ben Haller <email@hidden>
References: 
 >Re: NSTask with unzip (From: Ben Haller <email@hidden>)

  • Prev by Date: Re: iOS - Help with nasty memory leak
  • Next by Date: Icon Designer?
  • Previous by thread: Re: NSTask with unzip
  • Next by thread: Re: NSTask with unzip
  • Index(es):
    • Date
    • Thread