我正在为大型视频文件创建MD5校验和.我目前正在使用代码:
extension NSData { func MD5() -> Nsstring { let digestLength = Int(CC_MD5_DIGEST_LENGTH) let md5Buffer = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLength) CC_MD5(bytes,CC_LONG(length),md5Buffer) let output = NSMutableString(capacity: Int(CC_MD5_DIGEST_LENGTH * 2)) for i in 0..<digestLength { output.appendFormat("%02x",md5Buffer[i]) } return Nsstring(format: output) } }
但这会产生一个内存缓冲区,对于大型视频文件来说并不理想.在Swift中有没有办法计算读取文件流的MD5校验和,因此内存占用量最小?
解决方法
如图所示,您可以按块计算MD5校验和
例如在 Is there a MD5 library that doesn’t require the whole input at the same time?.
例如在 Is there a MD5 library that doesn’t require the whole input at the same time?.
以下是使用Swift的可能实现:
func md5File(url: URL) -> Data? { let bufferSize = 1024 * 1024 do { // Open file for reading: let file = try FileHandle(forReadingFrom: url) defer { file.closeFile() } // Create and initialize MD5 context: var context = CC_MD5_CTX() CC_MD5_Init(&context) // Read up to `bufferSize` bytes,until EOF is reached,and update MD5 context: while autoreleasepool(invoking: { let data = file.readData(ofLength: bufferSize) if data.count > 0 { data.withUnsafeBytes { _ = CC_MD5_Update(&context,$0,numericCast(data.count)) } return true // Continue } else { return false // End of file } }) { } // Compute the MD5 digest: var digest = Data(count: Int(CC_MD5_DIGEST_LENGTH)) digest.withUnsafeMutableBytes { _ = CC_MD5_Final($0,&context) } return digest } catch { print("Cannot open file:",error.localizedDescription) return nil } }
需要自动释放池来释放返回的内存
file.readData(),没有它的整个(可能是巨大的)文件
将被加载到内存中.感谢Abhi Beckert注意到这一点
并提供实施.
如果您需要将摘要作为十六进制编码的字符串,请更改
将类型返回到String?并替换
return digest
通过
let hexDigest = digest.map { String(format: "%02hhx",$0) }.joined() return hexDigest