我正在研究Objective C Cocoa應用程序。我測試CC_MD5 in CommonCrypto,它工作得很好;然而,當我給了它5G的文件時,我的整個計算機凍結並墜毀。 MD5算法將輸入處理爲512字節的塊,並不一次要求全部輸入。目標C或C中是否有一個庫要求下一個512字節塊,而不是一次採用所有輸入?是否有一個MD5庫不需要同時輸入整個輸入?
9
A
回答
11
還有就是在OBJ-C這裏計算的大型文件MD5一個偉大的線程: http://www.iphonedevsdk.com/forum/iphone-sdk-development/17659-calculating-md5-hash-large-file.html
下面是解有人想出有:
+(NSString*)fileMD5:(NSString*)path
{
NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
if(handle== nil) return @"ERROR GETTING FILE MD5"; // file didnt exist
CC_MD5_CTX md5;
CC_MD5_Init(&md5);
BOOL done = NO;
while(!done)
{
NSAutoreleasePool * pool = [NSAutoreleasePool new];
NSData* fileData = [handle readDataOfLength: CHUNK_SIZE ];
CC_MD5_Update(&md5, [fileData bytes], [fileData length]);
if([fileData length] == 0) done = YES;
[pool drain];
}
unsigned char digest[CC_MD5_DIGEST_LENGTH];
CC_MD5_Final(digest, &md5);
NSString* s = [NSString stringWithFormat: @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
digest[0], digest[1],
digest[2], digest[3],
digest[4], digest[5],
digest[6], digest[7],
digest[8], digest[9],
digest[10], digest[11],
digest[12], digest[13],
digest[14], digest[15]];
return s;
}
2
CC_MD5()
被設計用來處理所有它的輸入一次。 5GB可能比實際存儲在任何地方更多。對於更大的數據,如果您使用CC_MD5_CTX
,CC_MD5_Init()
,CC_MD5_Update()
和CC_MD5_Final()
,CommonCrypto可以一次對它進行大塊操作。查看CommonCrypto文檔或Google獲取更多信息和示例代碼。
2
這是一個更好的方法來使用dispatch apis來做到這一點,以獲得更高的效率。我在生產中使用它,它工作正常!
#import "CalculateMD5.h"
// Cryptography
#include <CommonCrypto/CommonDigest.h>
@implementation CalculateMD5
- (id)init
{
self = [super init];
if (self)
{
MD5ChecksumOperationQueue = dispatch_queue_create("com.test.calculateMD5Checksum", DISPATCH_QUEUE_SERIAL);
}
return self;
}
- (void)closeReadChannel
{
dispatch_async(MD5ChecksumOperationQueue, ^{
dispatch_io_close(readChannel, DISPATCH_IO_STOP);
});
}
- (void)MD5Checksum:(NSString *)pathToFile TCB:(void(^)(NSString *md5, NSError *error))tcb
{
// Initialize the hash object
__block CC_MD5_CTX hashObject;
CC_MD5_Init(&hashObject);
readChannel = dispatch_io_create_with_path(DISPATCH_IO_STREAM,
pathToFile.UTF8String,
O_RDONLY, 0,
MD5ChecksumOperationQueue,
^(int error) {
[self closeReadChannel];
});
if (readChannel == nil)
{
NSError* e = [NSError errorWithDomain:@"MD5Error"
code:-999 userInfo:@{
NSLocalizedDescriptionKey : @"failed to open file for calculating MD5."
}];
tcb(nil, e);
return;
}
dispatch_io_set_high_water(readChannel, 512*1024);
dispatch_io_read(readChannel, 0, SIZE_MAX, MD5ChecksumOperationQueue, ^(bool done, dispatch_data_t data, int error) {
if (error != 0)
{
NSError* e = [NSError errorWithDomain:@"ExamSoftMD5"
code:error userInfo:@{
NSLocalizedDescriptionKey : @"failed to read from file for calculating MD5."
}];
tcb(nil, e);
[self closeReadChannel];
return;
}
if (dispatch_data_get_size(data) > 0)
{
const void *buffer = NULL;
size_t size = 0;
data = dispatch_data_create_map(data, &buffer, &size);
CC_MD5_Update(&hashObject, (const void *)buffer, (CC_LONG)size);
}
if (done == YES)
{
// Compute the hash digest
unsigned char digest[CC_MD5_DIGEST_LENGTH];
CC_MD5_Final(digest, &hashObject);
// Compute the string result
char *hash = calloc((2 * sizeof(digest) + 1), sizeof(char));
for (size_t i = 0; i < sizeof(digest); ++i)
{
snprintf(hash + (2 * i), 3, "%02x", (int)(digest[i]));
}
tcb(@(hash), nil);
[self closeReadChannel];
}
});
}
@end
相關問題
- 1. 詢問用戶是否需要輸入多個輸入
- 2. 是否有一個用於實時視頻輸入的Python庫?
- 3. Cin需要2個輸入
- 4. 將兩個不同的輸出輸入到一個需要兩個輸入的命令中
- 5. 我需要輸入一個數字。如果不是,顯示請輸入數字,並再次要求輸入
- 6. 如何在一個輸入有兩個輸出時將一個輸入限制爲一個輸出?數據庫
- 7. 獲取一個unicode輸入,需要它是一個字符串
- 8. 是否需要輸入驗證?
- 9. JSON輸入過濾是否需要
- 10. 是否需要密碼輸入消毒?
- 11. Ç程序 - 需要,同時用戶輸入的輸入
- 12. 需要輸入
- 13. 在一個輸入表格中輸入兩個不同的值
- 14. 插入Cassandra時是否需要轉義數據輸入?
- 15. 確定一個pty是否有編程要求輸入
- 16. 我需要一個功能,我可以禁止字符輸入,我只需要用戶的整數輸入
- 17. jQuery來限制我有一個文本框,輸入需要輸入
- 18. 編寫一個輸入驗證循環,要求用戶輸入「是」或「否」
- 19. 同時輸入兩個uitextfield
- 20. 檢查輸入是否已經輸入到一個數組中
- 21. 如何檢查是否輸入了一個值使用輸入
- 22. 檢查用戶輸入是否是一個整數c#
- 23. C++函數檢查輸入是否是一個整數?
- 24. 檢查輸入是否是一個整數C
- 25. Angular 2 Custom Validator:檢查輸入值是否是一個整數?
- 26. 校驗和同時輸入一個輸入
- 27. RoR-檢查輸入是否是MD5散列或不是?
- 28. 爲什麼有一個文本輸入的FORM輸入,而有兩個文本INPUT的輸入不能輸入?
- 29. 需要檢查輸入是否是小數或不是
- 30. Java獲取整數輸入法需要輸入兩次
感謝您的鏈接,現在閱讀它。 –
這個答案會從ARC的更新中受益。循環中的代碼需要放在'@autoreleasepool {}'塊中。 –