学习IOS--获取文件的MD5值

一般我们在使用http或者socket上传或者下载文件的时候,经常会在完成之后经行一次MD5值得校验(尤其是在断点续传的时候用的更

多),校验MD5值是为了防止在传输的过程当中丢包或者数据包被篡改,在使用MD5之前呢我们应该先了解MD5的一些常识。MD5 百度百科

 

简单的来说:

1)、MD5是使用哈希算法计算文件或字符串的摘要,对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。128/ 8 = 16,也就是说MD5得到的是一组16字节长度的八进制。

2)、一般在使用的时候需要将它转换成十六进制输出,并且同时输出为小写。

在有了这些基础知识之后,计算MD5就没有那么大的难度了,最近在做大文件MD5计算的时候在网上搜到了一大堆ios MD5的代码,其中有一大部分都不能用,尤其是 使用

 NSFileHandle*  handle = [NSFileHandle fileHandleForReadingAtPath:_filePath]; 这种方法的,就最坑了,应为它永远读取的是文件的固定的位置,而并不是计算整个文件的MD5摘要,所以永远让你陷入尴尬的境地。例如:(

NSData* fileData = [handle readDataOfLength: 1024*8]; //永远读取的是从开始位置开始,1024*8长度的文件, 如果使用这种方法的话,必须在每次读取之前将文件读取的位置设置为指定的位置,应该使用NSFileHandle的 - (void)seekToFileOffset:(unsigned long long)offset;

下面贴上我找的能用的一段代码:亲测各个平台同一个计算出来的MD5值相同。(在使用的时候,可能会见

FileHashDefaultChunkSizeForReadingData 未定义的情况,那么你应该显示的在头文件里加入混定义:

#define FileHashDefaultChunkSizeForReadingData 1024*8 

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
+(NSString*)getFileMD5WithPath:(NSString*)path
 
{
 
    return (__bridge_transfer NSString *)FileMD5HashCreateWithPath((__bridge CFStringRef)path, FileHashDefaultChunkSizeForReadingData);
 
}
 
  
 
CFStringRef FileMD5HashCreateWithPath(CFStringRef filePath,size_t chunkSizeForReadingData) {
 
    // Declare needed variables
 
    CFStringRef result = NULL;
 
    CFReadStreamRef readStream = NULL;
 
    // Get the file URL
 
    CFURLRef fileURL =
 
    CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
 
                                  (CFStringRef)filePath,
 
                                  kCFURLPOSIXPathStyle,
 
                                  (Boolean)false);
 
    if (!fileURL) goto done;
 
    // Create and open the read stream
 
    readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault,
 
                                            (CFURLRef)fileURL);
 
    if (!readStream) goto done;
 
    bool didSucceed = (bool)CFReadStreamOpen(readStream);
 
    if (!didSucceed) goto done;
 
    // Initialize the hash object
 
    CC_MD5_CTX hashObject;
 
    CC_MD5_Init(&hashObject);
 
    // Make sure chunkSizeForReadingData is valid
 
    if (!chunkSizeForReadingData) {
 
        chunkSizeForReadingData = FileHashDefaultChunkSizeForReadingData;
 
    }   
 
    // Feed the data to the hash object
 
    bool hasMoreData = true;
 
    while (hasMoreData) {
 
        uint8_t buffer[chunkSizeForReadingData];
 
        CFIndex readBytesCount = CFReadStreamRead(readStream,(UInt8 *)buffer,(CFIndex)sizeof(buffer));
 
        if (readBytesCount == -1) break;
 
        if (readBytesCount == 0) {
 
            hasMoreData = false;
 
            continue;
 
        }
 
        CC_MD5_Update(&hashObject,(const void *)buffer,(CC_LONG)readBytesCount);
 
    }   
 
    // Check if the read operation succeeded
 
    didSucceed = !hasMoreData;
 
    // Compute the hash digest
 
    unsigned char digest[CC_MD5_DIGEST_LENGTH];
 
    CC_MD5_Final(digest, &hashObject);
 
    // Abort if the read operation failed
 
    if (!didSucceed) goto done;
 
    // Compute the string result
 
    char hash[2 * sizeof(digest) + 1];
 
    for (size_t i = 0; i < sizeof(digest); ++i) {
 
        snprintf(hash + (2 * i), 3, "%02x", (int)(digest[i]));
 
    }
 
    result = CFStringCreateWithCString(kCFAllocatorDefault,(const char *)hash,kCFStringEncodingUTF8);
 
     
 
done:
 
    if (readStream) {
 
        CFReadStreamClose(readStream);
 
        CFRelease(readStream);
 
    }
 
    if (fileURL) {
 
        CFRelease(fileURL);
 
    }
 
    return result;
 
}

  

学习IOS--获取文件的MD5值,,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。