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