在Cocoa中获取文件的类型

29

我已经成功找到了指定文件(JPEG图像、TIFF图像等)的扩展文件类型,但我正在寻找一些更通用的方法,可以将文件分类为“大类别”,例如图像、电影、文本文件等。

有没有办法在Cocoa(或Objective-C)中实现这一点?

感谢您的帮助。

5个回答

71
你可以使用统一类型标识符。由于UTI被组织成层次结构,一种可能的方法是检查给定文件的首选UTI是否符合顶级UTI,例如图像的public.image或电影的public.movie。核心服务框架包括操作UTI的函数以及表示已知UTI的常量。
例如,处理文件名扩展名:
NSString *file = @"…"; // path to some file
CFStringRef fileExtension = (CFStringRef) [file pathExtension];
CFStringRef fileUTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, fileExtension, NULL);

if (UTTypeConformsTo(fileUTI, kUTTypeImage)) NSLog(@"It's an image");
else if (UTTypeConformsTo(fileUTI, kUTTypeMovie)) NSLog(@"It's a movie");
else if (UTTypeConformsTo(fileUTI, kUTTypeText)) NSLog(@"It's text");

CFRelease(fileUTI);

如果您有 MIME 类型而不是文件名扩展名,可以使用 kUTTagClassMIMEType 而不是 kUTTagClassFilenameExtension

有关已知 UTI 的列表,请参见 此文档


3
如果你和我一样,在将文件扩展名符合正确的UTI方面遇到了问题,那么请确保不要在文件扩展名之前加上句点!你应该传递"jpg"而不是".jpg"! - Will
不幸的是,UTI检查似乎只适用于某些视频类型/文件。它可以很好地处理MP4容器(例如),但无法处理MKV容器。 UTTypeCreatePreferredIdentifierForTag在找不到合适的UTI时返回以“dyn”前缀开头的动态类型(例如,对于MKV)。 - Alex
你好,什么类型等同于doc/docx?谢谢。 - kemdo

14
[[NSWorkspace sharedWorkspace] typeOfFile:pathToFile error:nil]

6

检查路径是否为图像类型的示例,可以更改以匹配其他UTI类。请注意,Tech Note Technical Q&A QA1518使用FSPathMakeRef获取uti,但现在已被弃用,可以通过NSWorkspace解决方案获得UTI,然后只需要添加代码来与UTI列表进行比较:(如果需要,匹配数组可以预先分配和初始化/释放)

- (BOOL)isImageFile:(NSString*)filePath
{
/* get an array of utis to match against, this gets supported CG/NS image formats */

CFArrayRef supportedTypes = CGImageSourceCopyTypeIdentifiers();
CFIndex    typeCount      = CFArrayGetCount(supportedTypes);

/* get the uti of the filepath and check against the list with the UTI API */

BOOL isImage     = NO;
NSString * uti   = [[NSWorkspace sharedWorkspace] typeOfFile:filePath error:nil];

if ( uti != nil){
    for (CFIndex i = 0; i < typeCount; i++)
    {
        CFStringRef supportedUTI = CFArrayGetValueAtIndex(supportedTypes, i);
        if (UTTypeConformsTo(supportedUTI, CFSTR("public.image")))
        {
            if (UTTypeConformsTo((CFStringRef)uti, supportedUTI))
            {
                isImage = YES;
                break;
            }
        }
    } // i
}
/* clean up */
CFRelease(supportedTypes);
return isImage;
}

非常方便,感谢。对于有兴趣使用Swift版本的人,这里提供了一个URL扩展链接 - Todd

6

使用ImageIO框架的CGImageSource,您可以确定图像类型而无需依赖路径扩展名。

以下示例使用文件URL,但您也可以从CFDataRef创建图像源。

CFStringRef typeOfImageAtURL(NSURL *imageURL) {
    const void * keys[] = { kCGImageSourceShouldCache };
    const void * values[] = { kCFBooleanFalse };
    CFDictionaryRef options = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 1, NULL, NULL);
    CGImageSourceRef imageSource = CGImageSourceCreateWithURL((__bridge CFURLRef)imageURL, options);
    CFStringRef imageType = CGImageSourceGetType(imageSource);
    CFRelease(options);
    CFRelease(imageSource);
    return imageType;
}

返回值是一个常量,您可以将其与在CoreServices/MobileCoreServices中声明的统一类型标识符值(例如kUTTypeJPEG、kUTTypeGIF等)进行比较。

锦上添花的是:如果您有理由预期某种文件类型,则可以传入可选的“提示”UTI。将此方法与Bavarious'结合使用,您将拥有一个精简而高效的图像格式检测机器。


3
这将获取文件的“种类”。
+ (NSString *)humanReadableFileType:(NSString *)path{
    NSString *kind = nil;
    NSURL *url = [NSURL fileURLWithPath:[path stringByExpandingTildeInPath]];
    LSCopyKindStringForURL((CFURLRef)url, (CFStringRef *)&kind);
    return kind ? [kind autorelease] : @"";
}

来源: http://importantshock.wordpress.com/2007/01/07/cocoa-snippet-finding-a-files-kind/#post-19

这是一个关于如何查找文件类型的Cocoa代码片段。它通过获取文件的UTI(Uniform Type Identifier)并将其与系统预定义的UTI进行比较来确定文件类型。如果找不到匹配项,则返回“unknown”作为文件类型。

这是我正在使用的代码,它返回“JPEG图像”,“MP3音频”而不是“图像”,“音频”,“电影”等。 - AP.
LSCopyKindStringForURL现已被弃用。这个链接对我很有帮助。 - Todd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接