快速计算大文件的MD5校验和

我正在为大型视频文件创建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校验和,例如在?中有没有一个MD5库不需要同时输入全部内容?。

这是使用Swift的可能实现(现已针对Swift 5更新)

import CommonCrypto

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.baseAddress, numericCast(data.count))

}

return true // Continue

} else {

return false // End of file

}

}) { }

// Compute the MD5 digest:

var digest: [UInt8] = Array(repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))

_ = CC_MD5_Final(&digest, &context)

return Data(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

以上是 快速计算大文件的MD5校验和 的全部内容, 来源链接: utcz.com/qa/433545.html

回到顶部