How to compress a directory with NSData Category? - objective-c

I've been playing with an app and I wanted to add the ability to compress a directory and it's children. I found the CocoaDev category often mentioned on here but eventually settled on the category put together for Molecules. My problem is less with the compression category and more with converting a directory into a valid NSData object. I want people to be able to deflate the file with any app out there. I have looked into NSFileManager and serializing the directory contents and compressing that, but I suspect this would prohibit the archive from being deflatable.
Where am I going wrong? Would NSData not be sufficient?

sounds like zip -r (more arguments here) may work for you.

Related

Improving text file reading speed in Xcode?

I'm currently working on a project that involves a lot of text file reading. I need to get the contents of the files into NSStrings so I can go and manipulate them further. What I'm using:
NSString *file = [[NSBundle mainBundle] pathForResource:fileName ofType:#"txt"];
NSString *fileContents = [NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil];
It works well enough, but as my project grows so does the number of text files. I'm starting to think there should be a more efficient way of searching through the text files included in the project.
In many cases, I know exactly what file I want to search. I have the files organized into group folders based on when they need to be read. Is there any way to narrow the range of the initial file search? It seems like searching through the entire application bundle every time is pointless when I know where the files I need are on a more specific level.
Is there some way to search through groups as opposed to bundles? Can I somehow exclude certain files from the search? From what I can tell, defining custom bundles for this context would not be an appropriate use of the NSBundle functionality.
Have you looked at the method -[NSBundle pathForResource:ofType:inDirectory:]?
I had almost similar kind of situation, for more optimization, i had kept all resource file inside dictionary with some key ,
you may try following
1 -- in our application you may have some kind of pattern or where you could find major group,
2 -- have multiple dictionary each for each group, and inside group, you could store file name,
3 -- As ken suggested to go with the -[NSBundle pathForResource:ofType:inDirectory:]

Decompressing a gzip data stream in Objective-C

Is there a simple, standard way to decompress a gzip raw data buffer in Objective-C? I could not find anything useful in the Apple Developer documentation.
If not, can you point me to a code walk-through, a library, anything that will make my life easier? I am not afraid to write C code.
There is a NSData category available at cocoadev that can handle zlib and gzip data:
http://www.cocoadev.com/index.pl?NSDataCategory
If you just need gzip decompression, you can remove the zlib & hash related methods.
Don't forget to add a link libz.dylib (OS X standard library) build phase.
Update
As pointed out by marcos1490 in the comments, the original CocoaDev entry disappeared, but someone extended that NSData category and wrote about it: http://deusty.blogspot.de/2007/07/gzip-compressiondecompression.html
You can try Ziparchive for decompression. I've tried compressing files using it, hope the other would work perfectly.
Here is the code snippet
ZipArchive *zip = [ZipArchive alloc];
[zip UnzipOpenFile:Zip-File-Path];
[zip UnzipFileTo:Unzip-Folder-Path overWrite:As-You-Wish];
Also include libz.dylib in build phase.

Hiding (or encrypting) app resources?

I've developing a Cocoa app that has certain resources (images) which I wish to protect, but still display. Normally one would just place these in the resources folder, but storing there makes it quite easy to grab and use. Is there any way to keep these images hidden, but still access them within the app?
Simple solution:
Merge all files into one big data-file, optionally using 'salts'.
Then retrieve specific files with something like this:
NSData *dataFile = [NSData dataWithContentsOfFile:filePath];
NSData *theFile = [dataFile subdataWithRange: NSMakeRange(startPos,endPos)];
This does not really protect the files,
but prevents people simply dragging out the resources.
At least, the data-file is unusable, certainly with salts.
Another solution:
Create NSData object for every resource.
Add all objects to a NSMutableArray.
Convert the array to one big NSData object.
Write the NSData object to a file.
And add it to the resources folder.
Your app can then read the data-file.
And retrieve the array with the resources.
// Convert array to data
NSData* data=[NSKeyedArchiver archivedDataWithRootObject:theArray];
Use NSKeyedUnarchiver to retrieve the array again.
In order for you to protect the images in one big file, you can just dump the image data to a NSData object sequentially.
If you want, you can use either salts, as previously mentioned, or you can use AES encryption method, as shown here.
Then, you will have to either save the image files structurally (using an NSArray or similar) or record the image offsets so you can retrieve the image data blocks correctly.
This has some drawbacks, specially if your images change over time. That way you will have to monitor those changes and re-structure the file accordingly.
On other option is for you to simply mask the image files by changing name/extension to one of your choice. This will leave some users away from touch.
Finally, you can search for some archiving frameworks using zip like functions and keep the images there (as Blizzard uses in their MPQ format). This will be the best option (since it provides you with encryption methods and it abstracts you of the mechanisms of encryption and archiving) but it may not be easy to find such a framework.
Why do you want to protect the images? It goes without saying that anything you display can be recorded with a screenshot, so if you're trying to protect the images from the person viewing them, there isn't much point.
If you still want to protect them (say, some images should only be available to certain people), encrypting them on disk might be an option. I'm not an Objective-C guy, but this1 seems like a good place to look.

Use ZIP-archives to store NSDocument data

I noticed that Apple started using zip archives to replace document packages (folders appearing as a single file in Finder) in the iWork applications. I'm considering doing the same as I keep getting support emails related to my document packages getting corrupted when copying them to a windows fileserver.
My questions is what would be the best way to do this in a NSDocument-based application?
I guess the easiest way would be to create a directory file wrapper, create an archive of it and return it in NSDocument's
- (NSFileWrapper *)fileWrapperOfType:(NSString *)typeName error:(NSError **)outError
But I fail to understand how to create a zip archive of the NSFileWrapper.
If you just want to make a zip file your format (ie, "mydoc.myextension" is actually a zip file), there's no convenient, built-in Cocoa mechanism for creating zip archives with code. Take a look at this Google Code project: ziparchive I don't believe a file wrapper will help in that case, though.
Since you cited iWork, I don't own iWork 09, but previous versions use a package format (ie, NSFileWrapper would be ideal) but zip the XML that describes the document's structure, while keeping attachments (like embedded media, images, etc.) in a resource folder, all within the package. I assume they do this because XML can be quite large for large, complicated documents, but compresses very well because it's text. This results in an overall smaller document.
If indeed Apple has moved to making the entire document one big zip archive (which I would find odd), they'd either be extracting necessary resources to a temp folder somewhere or loading the whole thing into memory (a step backward from their package-based approach, IMO). These are considerations you'll need to take into account as well.
You’ll want to take the data from the file wrapper and feed it into something like ziparchive.
Pierre-Olivier Latour has written an extension to NSData that deals with zip compression. You can get it here: http://code.google.com/p/polkit/
I know this is a little late to the party but I thought I'd offer up another link that could help anyone that comes across this post.
Looks like the ZipBrowser sample from Apple would be a good start http://developer.apple.com/library/mac/#samplecode/ZipBrowser/Introduction/Intro.html
HTH

Accessing data files in Objective-C or cocoa

I am fairly new to a objective-c or in whole mac/iphone development. My question is how can I acces a data files(text files or flat files) in objective-c? For example I have a sample.txt file, how can I open this files and access its data? Do I need to use a class? And I heard about dictionary, is this term related to my problems?
Please kindly redirect me to a good site.
Thanks alot.
sasayins.
You can use regular fopen and fread to access the contents of a file. Alternatively, you can use NSString if your file contains only text or NSData for non-text data.
NSString *myString = [NSString stringWithContentsOfFile:#"/path/to/file"];
NSData *myData = [NSData dataWithContentsOfFile:#"/path/to/file"];
Edit
#"/path/to/file" a constant “Objective-C” style string. It is different to a regular C string (i.e. without the # prepended) because it behaves like an object; you can send it messages, and it is able to be stored in NSArrays etc. From a Mac Programmer's point of view, these Objective-C strings can be treated just like NSString objects.
The Mac OS X filesystem layout typically looks like this:
/System contains system files similar to C:\windows\
/Library contains libraries, similar to C:\windows\system32\
/Users similar to Windows' C:\Documents and Settings\
/Applications Mac's version of C:\Program Files\
/Developer Where Xcode, SDKs, and other developer tools live.
If your username on your Mac is "smith", then your Home directory is /Users/smith. If you have a file in your Documents folder of your Home directory called data.txt, then you can use the following code to access it (but I wouldn't recommend hard-coding paths like this)
NSString *myString = [NSString stringWithContentsOfFile:#"/Users/smith/Documents/data.txt"];
There are various functions available for reliably obtaining your home directory and other directories of particular interest. The NSString documentation explains the various methods available for manipulating strings containing paths.