8

我需要确定我的应用程序文档目录中的文件是否是 zip 文件。文件名不能用于进行此确定。所以我需要能够读取 MIME 类型或找到一些仅适用于 zip 的其他属性。

注意:需要将整个文件放入内存的解决方案并不理想,因为文件可能非常大。

4

4 回答 4

12

根据http://www.pkware.com/documents/casestudies/APPNOTE.TXT,一个 ZIP 文件以“本地文件头签名”开头

0x50, 0x4b, 0x03, 0x04

因此读取前 4 个字节就足以检查文件是否可能是 ZIP 文件。只有在您实际尝试提取文件时才能做出明确的决定。

很多方法可以读取文件的前 4 个字节。您可以使用 NSFileHandle、NSInputStream、打开/读取/关闭、...。所以这只能作为一个可能的例子:

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 ...
    }
}

斯威夫特 4 版本:

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()
}
于 2013-08-12T19:17:40.013 回答
0

尝试这个

NSWorkspace *ws = [NSWorkspace sharedWorkspace];
NSString *description = [ws localizedDescriptionForType:[ws typeOfFile:@"/full/path/to/file" error:nil]];

或者为了模仿这个

+ (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];
}
于 2013-08-12T19:11:14.887 回答
0

由于 .zip 和 .xlsx 具有相同的幻数,我找不到有效的 zip 文件(如果重命名)。

因此,我使用 Apache Tika 来查找确切的文档类型。

即使将文件类型重命名为 zip,它也会找到确切的类型。

参考Apache tika 用例

于 2019-09-23T14:03:31.277 回答
0

我只是使用file,然后 grep 如果它有文本“zip”或“Zip Archive”是安全的。

if file -q $FILENAME | grep "Zip archive"; then
  echo "zip";
else
  echo "not zip";
fi
于 2018-01-02T17:38:55.083 回答