ios獲取文件的MD5值


一般我們在使用http或者socket上傳或者下載文件的時候,經常會在完成之后經行一次MD5值得校驗(尤其是在斷點續傳的時候用的更

多),校驗MD5值是為了防止在傳輸的過程當中丟包或者數據包被篡改,在使用MD5之前呢我們應該先了解MD5的一些常識。MD5 百度百科

 

簡單的來說:

1)、MD5是使用哈希算法計算文件或字符串的摘要,對MD5算法簡要的敘述可以為:MD5以512位分組來處理輸入的信息,且每一分組又被划分為16個32位子分組,經過了一系列的處理后,算法的輸出由四個32位分組組成,將這四個32位分組級聯后將生成一個128位散列值。128/ 8 = 16,也就是說MD5得到的是一組16字節長度的八進制。

2)、一般在使用的時候需要將它轉換成十六進制輸出,並且同時輸出為小寫。

在有了這些基礎知識之后,計算MD5就沒有那么大的難度了,最近在做大文件MD5計算的時候在網上搜到了一大堆ios MD5的代碼,其中有一大部分都不能用,尤其是 使用

 NSFileHandle*  handle = [NSFileHandle fileHandleForReadingAtPath:_filePath]; 這種方法的,就最坑了,應為它永遠讀取的是文件的固定的位置,而並不是計算整個文件的MD5摘要,所以永遠讓你陷入尷尬的境地。例如:(

NSData* fileData = [handle readDataOfLength1024*8]; //永遠讀取的是從開始位置開始,1024*8長度的文件, 如果使用這種方法的話,必須在每次讀取之前將文件讀取的位置設置為指定的位置,應該使用NSFileHandle的 - (void)seekToFileOffset:(unsigned long long)offset;

下面貼上我找的能用的一段代碼:親測各個平台同一個計算出來的MD5值相同。(在使用的時候,可能會見

FileHashDefaultChunkSizeForReadingData 未定義的情況,那么你應該顯示的在頭文件里加入混定義:

#define FileHashDefaultChunkSizeForReadingData 1024*8 

代碼如下:

 

+(NSString*)getFileMD5WithPath:(NSString*)path

{

    return (__bridge_transfer NSString *)FileMD5HashCreateWithPath((__bridge CFStringRef)path, FileHashDefaultChunkSizeForReadingData);

}

 

CFStringRef FileMD5HashCreateWithPath(CFStringRef filePath,size_t chunkSizeForReadingData) {

    // Declare needed variables

    CFStringRef result = NULL;

    CFReadStreamRef readStream = NULL;

    // Get the file URL

    CFURLRef fileURL =

    CFURLCreateWithFileSystemPath(kCFAllocatorDefault,

                                  (CFStringRef)filePath,

                                  kCFURLPOSIXPathStyle,

                                  (Boolean)false);

    if (!fileURL) goto done;

    // Create and open the read stream

    readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault,

                                            (CFURLRef)fileURL);

    if (!readStream) goto done;

    bool didSucceed = (bool)CFReadStreamOpen(readStream);

    if (!didSucceed) goto done;

    // Initialize the hash object

    CC_MD5_CTX hashObject;

    CC_MD5_Init(&hashObject);

    // Make sure chunkSizeForReadingData is valid

    if (!chunkSizeForReadingData) {

        chunkSizeForReadingData = FileHashDefaultChunkSizeForReadingData;

    }    

    // Feed the data to the hash object

    bool hasMoreData = true;

    while (hasMoreData) {

        uint8_t buffer[chunkSizeForReadingData];

        CFIndex readBytesCount = CFReadStreamRead(readStream,(UInt8 *)buffer,(CFIndex)sizeof(buffer));

        if (readBytesCount == -1break;

        if (readBytesCount == 0) {

            hasMoreData = false;

            continue;

        }

        CC_MD5_Update(&hashObject,(const void *)buffer,(CC_LONG)readBytesCount);

    }    

    // Check if the read operation succeeded

    didSucceed = !hasMoreData;

    // Compute the hash digest

    unsigned char digest[CC_MD5_DIGEST_LENGTH];

    CC_MD5_Final(digest, &hashObject);

    // Abort if the read operation failed

    if (!didSucceed) goto done;

    // Compute the string result

    char hash[2 * sizeof(digest) + 1];

    for (size_t i = 0; i < sizeof(digest); ++i) {

        snprintf(hash + (2 * i), 3"%02x", (int)(digest[i]));

    }

    result = CFStringCreateWithCString(kCFAllocatorDefault,(const char *)hash,kCFStringEncodingUTF8);

    

done:

    if (readStream) {

        CFReadStreamClose(readStream);

        CFRelease(readStream);

    }

    if (fileURL) {

        CFRelease(fileURL);

    }

    return result;

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM