2017-03-21 85 views
4

我正在爲大視頻文件創建MD5校驗和。我目前正在使用的代碼:Swift計算大文件的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校驗和,因此內存佔用量會很小?

+0

考慮使用CC_MD5_Init'的'正確的組合, 'CC_MD5_Update'和'CC_MD5_Final'。 – rmaddy

回答

8

您可以計算塊中的MD5校驗和,如演示 在Is there a MD5 library that doesn't require the whole input at the same time?

下面是使用斯威夫特一個可能的實現:需要

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 
+1

對於任何使用此代碼的人,您都需要更新以匹配我剛剛編輯的編輯,因爲它將整個文件存儲在當前的自動釋放池中,可能會消耗數十GB的內存。 –

+0

@AbhiBeckert:事實上,這有很大的不同。感謝更新!我已經修改了一些代碼來擺脫額外的退出變量,但這純粹是個人選擇的問題。 –