私はObjective C Cocoaアプリケーションに取り組んでいます。私はCC_MD5 in CommonCryptoをテストしましたが、うまくいきました。しかし、私はそれに5ギガバイトのファイルを与えたとき、私のコンピュータ全体が凍ってクラッシュしました。 MD5アルゴリズムは512バイトのチャンクとして入力を処理し、すべての入力を一度に必要としません。 Objective 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
ディスパッチAPIを使用して効率を上げるより良い方法があります。私はプロダクションでそれを使用しており、うまくいきます!
#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. ある時間から全体時間と部分時間を分割する必要があります(postgresql)
- 2. 2つの異なるMD5が同じ入力にありますか?
- 3. 入力パラメータを1つずつエスケープするか、SQLクエリ全体をエスケープする必要がありますか?
- 4. Excelセルに入力すると検索する必要があります。アクティブコントロールを必要としない
- 5. C++ランタイムを必要としないSQLite用のC#ライブラリはありますか?
- 6. ブーストを必要としないコネクタ/ C++ライブラリはありますか?
- 7. トレーニングデータ用にテキスト全体を必要としないエンティティ認識器分類器アルゴリズムがありますか?
- 8. C#MD5ハッシングはJava MD5と同じではありません
- 9. すべてのcom.google.android.gmsライブラリは完全に同じバージョン仕様を使用する必要がありますか?
- 10. Windowsシステムのロケールはシステム全体である必要がありますか?
- 11. 特定の要素をクリックすると、入力時に.blur()をアクティブにする必要はありません
- 12. テキストエリアや入力に必要な単語があります
- 13. サイトマップはサイト全体をカバーする必要がありますか?
- 14. いつjavaに "new"と入力する必要がありますか?
- 15. JavaScriptコード全体をjQueryに書き直す必要がありますか?
- 16. はNCFTPシェルスクリプトに入力する必要があります
- 17. Twitter Bootstrapと同時にDatePickerを使用する必要がありますか?
- 18. ボタンは親ラジオボタンを入力する必要があります
- 19. GWT wrap()メソッドはDOM全体を不必要に繰り返しますか?
- 20. Railsはユーザー入力とタグを同時に出力します
- 21. Angular2は、キー入力またはキーダウン時に入力値全体を取得します
- 22. の時間のjavax.persistenceに入力する(一時的なタイプを指定する必要があります)
- 23. ユーザから入力1または2を取得し、入力ボタンモデルをクリックすると、入力に基づいて変更する必要があります
- 24. ライブラリが不正なポインタ入力でSIGSEGVを処理する必要がありますか?
- 25. 必要なライブラリを生成したJARファイルにいつ展開する必要がありますか?
- 26. 入力が必要なプログラムは、大文字と小文字を区別する必要があります。
- 27. 展開時にCloud Endpoints Frameworksライブラリを含める必要がありますか?
- 28. Railsでディレクトリツリー全体を必要とする良い方法はありますか?
- 29. 入力値に2を加える必要があります
- 30. メソッド呼び出し時に青いjで入力する必要がありますか?
リンクをありがとうございました。 –
この回答はARCのアップデートの恩恵を受けるでしょう。ループ内のコードは '@autoreleasepool {}'ブロックの中に置く必要があります。 –