Access any file inside Zip File [duplicate] - ios

I'm trying to port an existing Android application to iOS,
In the Android application i was using a ZipInputStream to extract a single file from the zip archive and store it in as a temporary file.
How could i extract a single file from a Zip Archive without having to extract the whole archive (As it is very large)?

I just found the answer,
I had to modify SSZipArchive to insert a method that will extract a single file from the ZIP archive (Based on its name)
You could find the modified version here, if someone finds this useful i might clean it up, add the delegate, the tests and propose for pull in SSZipArchive.
Usage is straightforward:
NSString *zipEntityToExtract = #"example.aac";
NSString *destinationFilePath = ...; //(Includes filename)
NSString *zipPath = ...;
[SSZipArchive unzipEntityName:zipEntityToExtract fromFilePath:zipPath toDestination:filePath];
//File is now in destinationFilePath

Related

Objective Zip archives aren't opened by ArchiveUtility.app

I'm using ObjectiveZip library (which is a wrapper for MiniZip) in my iOS app. My app sends .zip archives to server, where they are processed manually by moderator. Here's my code for creating an archive:
NSString * zipfile = [Result zipfilePathWithResult:self];
ZipFile * zf = [[ZipFile alloc] initWithFileName:zipfile mode:ZipFileModeCreate];
ZipWriteStream * zws = [zf writeFileInZipWithName:#"report.xml" compressionLevel:ZipCompressionLevelNone];
[zws writeData:[xml dataUsingEncoding:NSUTF8StringEncoding]];
[zws finishedWriting];
for (NSString * name in mediaFiles)
{
ZipWriteStream * zws = [zf writeFileInZipWithName:name compressionLevel:ZipCompressionLevelNone];
[zws writeData:[files objectForKey:name]];
[zws finishedWriting];
}
[zf close];
Unfortunately, these archives aren't correctly processed by default OS X ArchiveUtility: it always unarchives my files into zip.cpgz, regardless of the actual content of archive (usually it's a .xml file and a few .jpg files).
However, some other applications on OS X and also on Windows are able to open my archives correctly, so the archive isn't actually broken.
Is there a way to make ObjectiveZip work with ArchiveUtility? Or maybe you can suggest any other objective-c library for creating .zip files which can do it. Thanks in advance!
Edit zip.c changing the parameters passed into each calls to zipOpenNewFileInZip3_64. The last parameter being passed into each method is a 1. Change it to a 0 and it will work
Changing the last parameter to zipOpenNewFileInZipX_64 function is one way to fix this but changing this parameter to 0 means setting zip64, i.e large file zipping capability, to false.
I was able to fix this by setting second parameter of zip64local_putValue call to (uLong)20(which is currently 45 in one case) inside the function Write_LocalFileHeader regardless of value of zi->ci.zip64.

Unzipping a single file from Archive

I'm trying to port an existing Android application to iOS,
In the Android application i was using a ZipInputStream to extract a single file from the zip archive and store it in as a temporary file.
How could i extract a single file from a Zip Archive without having to extract the whole archive (As it is very large)?
I just found the answer,
I had to modify SSZipArchive to insert a method that will extract a single file from the ZIP archive (Based on its name)
You could find the modified version here, if someone finds this useful i might clean it up, add the delegate, the tests and propose for pull in SSZipArchive.
Usage is straightforward:
NSString *zipEntityToExtract = #"example.aac";
NSString *destinationFilePath = ...; //(Includes filename)
NSString *zipPath = ...;
[SSZipArchive unzipEntityName:zipEntityToExtract fromFilePath:zipPath toDestination:filePath];
//File is now in destinationFilePath

Edit Programmatically plist in the App bundle at development time

I have created a plist on XCode that will have a few values that I can't insert manually. So I want to add this values programmatically at development time. But it seems that I can only read the plist I can not save a plist that is on the App bundle, which makes sense at runtime.. When I will distribute my app I want everyone to have this plist file that's why I am not saving on documents or cache. How can I achieve what I want?
From http://www.karelia.com/cocoa_legacy/Foundation_Categories/NSFileManager__Get_.m (pasted below) you can build a path within the user's personal library with the -(NSString *) pathFromUserLibraryPath:(NSString *)inSubPath method found there.
For example, NSString *editedPlist = [self pathFromUserLibraryPath:#"my.plist"]; gets you the name of the modified plist within the user's library (even if that plist doesn't exist yet).
How you read/write it is according to what kind of plist you have, but you could read it into a dictionary with:
NSMutableDictionary *thePlist= [[NSMutableDictionary alloc] initWithContentsOfFile:editedPlist ];
If you are unable to read, easily detected by, for example [thePlist count] == 0, then you would instead call the same initWithContentsOfFile: initializer with a path to the template within your bundle, but you would then write the plist out to the editedPlist path so it appears in the user directory.
Here is the utility method I referenced above:
/*
NSFileManager: Get the path within the user's Library directory
Original Source: <http://cocoa.karelia.com/Foundation_Categories/NSFileManager__Get_.m>
(See copyright notice at <http://cocoa.karelia.com>)
*/
/*" Return the path in the user library path of the given sub-path. In other words, if given inSubPath is "foo", the path returned will be /Users/myUser/Library/foo
"*/
- (NSString *) pathFromUserLibraryPath:(NSString *)inSubPath
{
NSArray *domains = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,NSUserDomainMask,YES);
NSString *baseDir= [domains objectAtIndex:0];
NSString *result = [baseDir stringByAppendingPathComponent:inSubPath];
return result;
}
What I would suggest is writing code that checks for the plist in the documents directory at start. If it's there, read it into memory.
If you don't find the file in the documents directory, read it from the app bundle instead. Then drop into the code that uses it from memory and writes the changed version to the documents directory.
Remember that all the objects you read from a plist file are read as immutable, even if you wrote mutable objects into the file. You have to write code that makes mutable copies of anything that you want to change. (And have to implement a mutable deep copy if you have complex structures like arrays of dictionaries that in turn contain arrays of strings.)

how to zip empty folders in File manager in iOS?

I am developing a app like file manager. In this i have created zip folder using any existing folder, it works perfectly fine. For this i have used SSZipArchive API. After zip i send it through mail. It's working fine too.
Now when i try to zip any empty folder, it is not working. Means empty folder does not zip.
Yeah looking at the source code, the method + createZipFileAtPath:withContentsOfDirectory: only appears to care about files:
while ((fileName = [dirEnumerator nextObject])) {
BOOL isDir;
NSString *fullFilePath = [directoryPath stringByAppendingPathComponent:fileName];
[fileManager fileExistsAtPath:fullFilePath isDirectory:&isDir];
if (!isDir) {
[zipArchive writeFileAtPath:fullFilePath withFileName:fileName];
}
}
You have two choices:
Fix it yourself and then send a pull request to the author on github and contribute to work you have, yourself, benefited from.
Live with it. It's not clear how an empty folder not appearing in the zip file is an issue anyway.
Isn't a standard thing to have stub files in directories like that. Some file with no contents.

parsing XML located inside the project

This is the first time i'm going to parse an XML file with Xcode and it differs a bit from what I'm used to...
I read these 2 docs :
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/XMLParsing/Articles/UsingParser.html
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/XMLParsing/Articles/HandlingElements.html#//apple_ref/doc/uid/20002265-BCIJFGJI
I understand what's going on... But I still got one question. How can I do to parse an XML file which is located directly inside the project (I mean, for example in the resource file, where I usually put my images?). They usually show how to get the url of the XML file..But it's not the case here. It's going to be loaded directly on the iPad, among images and everything...
You Simply have to give the path of a local file :-
NSString *myFile= [documentsDirectory stringByAppendingPathComponent:#"youFile.xml"];
NSURL *xmlFile = [NSURL fileURLWithPath:myFile];
NSXMLParser *parser= [[NSXMLParser alloc] initWithContentsOfURL:xmlFile];
This is just an example implement your own login , use above two lines to get the path of local file.

Resources