项目中有一个需求:

给定一个NSData *类型的数据,从中解析出文件类型。

图片后缀判断

typedef NSInteger ImageFormat NS_TYPED_EXTENSIBLE_ENUM;
static const ImageFormat ImageFormatUndefined = -1;
static const ImageFormat ImageFormatJPEG      = 0;
static const ImageFormat ImageFormatPNG       = 1;
static const ImageFormat ImageFormatGIF       = 2;
static const ImageFormat ImageFormatTIFF      = 3;
static const ImageFormat ImageFormatWebP      = 4;
static const ImageFormat ImageFormatHEIC      = 5;
static const ImageFormat ImageFormatHEIF      = 6;

+ (ImageFormat)imageFormatForImageData:(nullable NSData *)data {
    if (!data) {
        return ImageFormatUndefined;
    }
    
    // File signatures table: <http://www.garykessler.net/library/file_sigs.html>
    uint8_t c;
    [data getBytes:&c length:1];
    switch (c) {
        case 0xFF:
            return ImageFormatJPEG;
        case 0x89:
            return ImageFormatPNG;
        case 0x47:
            return ImageFormatGIF;
        case 0x49:
        case 0x4D:
            return ImageFormatTIFF;
        case 0x52: {
            if (data.length >= 12) {
                //RIFF....WEBP
                NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
                if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
                    return ImageFormatWebP;
                }
            }
            break;
        }
        case 0x00: {
            if (data.length >= 12) {
                //....ftypheic ....ftypheix ....ftyphevc ....ftyphevx
                NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(4, 8)] encoding:NSASCIIStringEncoding];
                if ([testString isEqualToString:@"ftypheic"]
                    || [testString isEqualToString:@"ftypheix"]
                    || [testString isEqualToString:@"ftyphevc"]
                    || [testString isEqualToString:@"ftyphevx"]) {
                    return ImageFormatHEIC;
                }
...

文件后缀判断


- (void)getFileExtension {
    NSString *path = [[NSBundle mainBundle] pathForResource:@"2019工资单 (1)" ofType:@"docx"];
    NSData *data = [NSData dataWithContentsOfFile:path];
    NSString *extension = [self contentTypeForImageData:data];
    NSLog(@"%@", extension);
}

- (NSString *)contentTypeForImageData:(NSData *)data {
    const NSInteger maxLength = 28;
    Byte headBytes[maxLength];
    [data getBytes:headBytes length:maxLength];
    
    NSString *headStr = [self hexStringFromByte:headBytes];
    
    NSDictionary *dict = [self dict];
    for (NSString *key in dict) {
        if ([headStr hasPrefix:[key uppercaseString]]) {
            return dict[key];
        }
    }
    return @"";
}

- (NSString *)hexStringFromByte:(Byte *)byta {
    // 转16进制
    NSString *hexStr = @"";
    for(int i = 0; i < 28; i++) {
        NSString *newHexStr = [NSString stringWithFormat:@"%x",byta[i]&0xff];///16进制数
        if([newHexStr length]==1)
            hexStr = [NSString stringWithFormat:@"%@0%@",hexStr,newHexStr];
        else
            hexStr = [NSString stringWithFormat:@"%@%@",hexStr,newHexStr];
    }
    return [hexStr uppercaseString];
}

- (NSDictionary *)dict {
    return @{
        @"FFD8FF" : @"JPEG" ,
        @"89504E47" : @"PNG",
        @"47494638" : @"GIF",
        @"49492A00" : @"TIFF",
        @"424D" : @"BMP",
        @"41433130" : @"DWG", // CAD
        @"38425053" : @"PSD", // Adobe Photoshop
        @"7B5C727466" : @"RTF", // Rich Text Format
        @"3C3F786D6C" : @"XML", // XML
        @"68746D6C3E" : @"HTML", // HTML
        @"48544D4C207B0D0A0942" : @"CSS", // CSS
        @"696B2E71623D696B2E71" : @"JS", // JS
        @"44656C69766572792D646174653A" : @"EML", //Email [thorough only].
        @"CFAD12FEC5FD746F" : @"DBX", // Outlook Express.
        @"2142444E" : @"PST", // Outlook (pst).
        @"D0CF11E0" : @"XLS_DOC", // MS Word/Excel
        @"504B0304" : @"XLSX_DOCX", // MS Word/Excel
        @"255044462D" : @"PDF", // PDF
        @"53746...