Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding large filles problem #22

Open
GoogleCodeExporter opened this issue Oct 29, 2015 · 2 comments
Open

Adding large filles problem #22

GoogleCodeExporter opened this issue Oct 29, 2015 · 2 comments

Comments

@GoogleCodeExporter
Copy link

1. On some devices (iPad in my case) trying to add a large file in 
     -(BOOL) addFileToZip:(NSString*) file newname:(NSString*) newname;
     will crash the app because the method
     [NSData dataWithContentsOfFile:] 
     will use up all the memory.

I fixed the issue for my particular problem with zip files that have no 
password by changing the addFileToZip method a bit. You might want to take a 
look at it and change it universally... Also there is no internal autorelease 
pool needed when adding multiple files.

The methode:

#define M_FRAGMENT_SIZE 10000000
-(BOOL) addFileToZip:(NSString*) file newname:(NSString*) newname;
{
    if( !_zipFile )
        return NO;

//  tm_zip filetime;
    time_t current;
    time( &current );

    zip_fileinfo zipInfo = {0};
//  zipInfo.dosDate = (unsigned long) current;

    NSDictionary* attr = [[NSFileManager defaultManager] attributesOfItemAtPath:file error:nil];
    if( attr )
    {
        NSDate* fileDate = (NSDate*)[attr objectForKey:NSFileModificationDate];
        if( fileDate )
        {
            // some application does use dosDate, but tmz_date instead
        //  zipInfo.dosDate = [fileDate timeIntervalSinceDate:[self Date1980] ];
            NSCalendar* currCalendar = [NSCalendar currentCalendar];
            uint flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | 
                NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit ;
            NSDateComponents* dc = [currCalendar components:flags fromDate:fileDate];
            zipInfo.tmz_date.tm_sec = [dc second];
            zipInfo.tmz_date.tm_min = [dc minute];
            zipInfo.tmz_date.tm_hour = [dc hour];
            zipInfo.tmz_date.tm_mday = [dc day];
            zipInfo.tmz_date.tm_mon = [dc month] - 1;
            zipInfo.tmz_date.tm_year = [dc year];
        }
    }

    int ret ;
    NSData* data = nil;
    if( [_password length] == 0 )
    {
        ret = zipOpenNewFileInZip( _zipFile,
                                  (const char*) [newname UTF8String],
                                  &zipInfo,
                                  NULL,0,
                                  NULL,0,
                                  NULL,//comment
                                  Z_DEFLATED,
                                  Z_DEFAULT_COMPRESSION );
    }
    else
    {
        FILE *f = fopen([file cStringUsingEncoding:NSUTF8StringEncoding], "r");
        fseek(f, 0, SEEK_END);
        long fLenght = ftell(f);
        void *fBuffer = malloc(fLenght);
        fread(fBuffer, 1, fLenght, f);
        fclose(f);
        data = [[NSData alloc] initWithBytesNoCopy:fBuffer length:fLenght];
        uLong crcValue = crc32( 0L,NULL, 0L );
        crcValue = crc32( crcValue, (const Bytef*)[data bytes], [data length] );
        ret = zipOpenNewFileInZip3( _zipFile,
                                  (const char*) [newname UTF8String],
                                  &zipInfo,
                                  NULL,0,
                                  NULL,0,
                                  NULL,//comment
                                  Z_DEFLATED,
                                  Z_DEFAULT_COMPRESSION,
                                  0,
                                  15,
                                  8,
                                  Z_DEFAULT_STRATEGY,
                                  [_password cStringUsingEncoding:NSASCIIStringEncoding],
                                  crcValue );
    }
    if( ret!=Z_OK )
    {
        [data release];
        return NO;
    }

// M_FRAGMENT_SIZE 10000000 (10MB)
    FILE *f = fopen([file cStringUsingEncoding:NSUTF8StringEncoding], "r");
    if(!f)
        return NO;

    fseek(f, 0, SEEK_END);
    long fLenght = ftell(f);
    rewind(f);
    void *fBuffer = malloc(M_FRAGMENT_SIZE);

    for (;fLenght > M_FRAGMENT_SIZE; fLenght-=M_FRAGMENT_SIZE) {        
        fread(fBuffer, 1, M_FRAGMENT_SIZE, f);
        ret = zipWriteInFileInZip( _zipFile, (const void*)fBuffer, M_FRAGMENT_SIZE);
    }   
    if(fLenght) {
        fread(fBuffer, 1, fLenght, f);
        ret = zipWriteInFileInZip( _zipFile, (const void*)fBuffer, fLenght);
        if( ret!=Z_OK )
        {
            free(fBuffer);
            fclose(f);
            return NO;
        }
    }
    free(fBuffer);
    fclose(f);

    if( ret!=Z_OK )
    {
        return NO;
    }
    ret = zipCloseFileInZip( _zipFile );
    if( ret!=Z_OK )
        return NO;
    return YES;
}

Now the memory consumption is restricted by M_FRAGMENT_SIZE in bytes, currently 
10MB and it seems to work great...



Original issue reported on code.google.com by [email protected] on 21 Apr 2011 at 10:02

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant