Reputation: 2505
I need to determine if a file in my app's documents directory is a zip file. The file name cannot be used in making this determination. So I will need to be able read the MIME type or find some other property that only applies to zips.
NOTE: A solution that requires putting the entire file into memory is not ideal as files could potentially be pretty large.
Upvotes: 10
Views: 14383
Reputation: 539705
According to http://www.pkware.com/documents/casestudies/APPNOTE.TXT, a ZIP file starts with the "local file header signature"
0x50, 0x4b, 0x03, 0x04
so it is sufficient to read the first 4 bytes to check if the file is possibly a ZIP file. A definite decision can only be made if you actually try to extract the file.
There are many methods to read the first 4 bytes of a file. You can use NSFileHandle, NSInputStream, open/read/close, ... . So this should only be taken as one possible example:
NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:@"/path/to/file"];
NSData *data = [fh readDataOfLength:4];
if ([data length] == 4) {
const char *bytes = [data bytes];
if (bytes[0] == 'P' && bytes[1] == 'K' && bytes[2] == 3 && bytes[3] == 4) {
// File starts with ZIP magic ...
}
}
Swift 4 version:
if let fh = FileHandle(forReadingAtPath: "/path/to/file") {
let data = fh.readData(ofLength: 4)
if data.starts(with: [0x50, 0x4b, 0x03, 0x04]) {
// File starts with ZIP magic ...
}
fh.closeFile()
}
Upvotes: 17
Reputation: 304
I'd just use file, then grep if it has the text "zip" or "Zip Archive" to be safe.
if file -q $FILENAME | grep "Zip archive"; then
echo "zip";
else
echo "not zip";
fi
Upvotes: 0
Reputation: 559
Try this
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
NSString *description = [ws localizedDescriptionForType:[ws typeOfFile:@"/full/path/to/file" error:nil]];
Or for mime this
+ (NSString*) mimeTypeForFileAtPath: (NSString *) path {
if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
return nil;
}
CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)[path pathExtension], NULL);
CFStringRef mimeType = UTTypeCopyPreferredTagWithClass (UTI, kUTTagClassMIMEType);
CFRelease(UTI);
if (!mimeType) {
return @"application/octet-stream";
}
return [NSMakeCollectable((NSString *)mimeType) autorelease];
}
Upvotes: 0