md5file.cpp 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. #include "md5file.h"
  2. #include "md5global.h"
  3. #include "md5.h"
  4. #include <fstream>
  5. #include <sstream>
  6. #include <memory>
  7. #include <iomanip>
  8. #include <exception>
  9. std::string getFileMD5(const std::string& filename)
  10. {
  11. std::ifstream fin(filename.c_str(), std::ifstream::in | std::ifstream::binary);
  12. if (fin)
  13. {
  14. MD5_CTX context;
  15. MD5Init(&context);
  16. fin.seekg(0, fin.end);
  17. const auto fileLength = fin.tellg();
  18. fin.seekg(0, fin.beg);
  19. const int bufferLen = 8192;
  20. std::unique_ptr<unsigned char[]> buffer{ new unsigned char[bufferLen] {} };
  21. unsigned long long totalReadCount = 0;
  22. decltype(fin.gcount()) readCount = 0;
  23. // 读取文件内容,调用MD5Update()更新MD5值
  24. while (fin.read(reinterpret_cast<char*>(buffer.get()), bufferLen))
  25. {
  26. readCount = fin.gcount();
  27. totalReadCount += readCount;
  28. MD5Update(&context, buffer.get(), static_cast<unsigned int>(readCount));
  29. }
  30. // 处理最后一次读到的数据
  31. readCount = fin.gcount();
  32. if (readCount > 0)
  33. {
  34. totalReadCount += readCount;
  35. MD5Update(&context, buffer.get(), static_cast<unsigned int>(readCount));
  36. }
  37. fin.close();
  38. // 数据完整性检查
  39. if (totalReadCount != fileLength)
  40. {
  41. std::ostringstream oss;
  42. oss << "FATAL ERROR: read " << filename << " failed!" << std::ends;
  43. throw std::runtime_error(oss.str());
  44. }
  45. unsigned char digest[16];
  46. MD5Final(digest, &context);
  47. // 获取MD5
  48. std::ostringstream oss;
  49. for (int i = 0; i < 16; ++i)
  50. {
  51. oss << std::hex << std::setw(2) << std::setfill('0') << static_cast<unsigned int>(digest[i]);
  52. }
  53. oss << std::ends;
  54. return std::move(oss.str());
  55. }
  56. else
  57. {
  58. std::ostringstream oss;
  59. oss << "FATAL ERROR: " << filename << " can't be opened" << std::ends;
  60. throw std::runtime_error(oss.str());
  61. }
  62. }