Swift calcula MD5 Checksum para files grandes

Estoy trabajando para crear MD5 Checksum para files de video grandes. Actualmente estoy usando el código:

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) } } 

Pero eso crea un búfer de memory, y para los files de video grandes no sería ideal. ¿Hay alguna manera en Swift de calcular el MD5 Checksum leyendo una secuencia de files, por lo que la huella de memory será mínima?

Puede calcular la sum de comprobación MD5 en fragments, como se demostró, por ejemplo, en ¿Existe una biblioteca MD5 que no requiere la input completa al mismo time? .

Aquí hay una posible implementación usando 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 } } 

El grupo de autorelease es necesario para liberar la memory devuelta por file.readData() , sin él, todo el file (potencialmente enorme) se cargaría en la memory. Gracias a Abhi Beckert por notarlo y por proporcionar una implementación.

Si necesita el resumen como una cadena codificada en hexadecimales, ¿cambiar el tipo de retorno a String? y replace

 return digest 

por

 let hexDigest = digest.map { String(format: "%02hhx", $0) }.joined() return hexDigest 
    Intereting Posts