【发布时间】:2015-05-26 09:39:24
【问题描述】:
我正在尝试计算文件的 SHA-256。我有以下代码在路径有效时给出正确的校验和值,即。它是 ASCII。我有以下代码:
#include <openssl\evp.h>
#include <sys\stat.h>
#include <iostream>
#include <string>
#include <fstream>
#include <cstdio>
const int MAX_BUFFER_SIZE = 1024;
std::string FileChecksum(std::string, std::string);
long long int GetFileSize(std::string filename)
{
struct _stat64 stat_buf;
int rc = _stat64(filename.c_str(), &stat_buf);
return rc == 0 ? stat_buf.st_size : -1;
}
std::string fname = "D:\\Private\\Test\\asdf.txt"; // Need to support this D:\\Private\\Test\\सर्वज्ञ पन्त.txt
int main()
{
std::string checksum = FileChecksum(fname , "sha256");
std::cout << checksum << std::endl;
return 0;
}
static std::string FileChecksum(std::string file_path, std::string algorithm="sha256")
{
EVP_MD_CTX *mdctx;
const EVP_MD *md;
unsigned char md_value[EVP_MAX_MD_SIZE];
int i;
unsigned int md_len;
OpenSSL_add_all_digests();
md = EVP_get_digestbyname(algorithm.c_str());
if(!md) {
printf("Unknown message digest %s\n",algorithm);
return "";
}
mdctx = EVP_MD_CTX_create();
std::ifstream readfile(file_path,std::ifstream::binary);
if(!readfile.is_open())
{
std::cout << "COuldnot open file\n";
return "";
}
readfile.seekg(0, std::ios::end);
long long filelen = readfile.tellg();
std::cout << "LEN IS " << filelen << std::endl;
readfile.seekg(0, std::ios::beg);
if(filelen == -1)
{
std::cout << "Return Null \n";
return "";
}
EVP_DigestInit_ex(mdctx, md, NULL);
long long temp_fil = filelen;
while(!readfile.eof() && readfile.is_open() && temp_fil>0)
{
int bufferS = (temp_fil < MAX_BUFFER_SIZE) ? temp_fil : MAX_BUFFER_SIZE;
char *buffer = new char[bufferS+1];
buffer[bufferS] = 0;
readfile.read(buffer, bufferS);
EVP_DigestUpdate(mdctx, buffer, bufferS);
temp_fil -= bufferS;
delete[] buffer;
}
EVP_DigestFinal_ex(mdctx, md_value, &md_len);
EVP_MD_CTX_destroy(mdctx);
char str[128] = { 0 };
char *ptr = str;
std::string ret;
for(i = 0; i < md_len; i++)
{
//_snprintf(checksum_msg+cx,md_len-cx,"%02x",md_value[i]);
sprintf(ptr,"%02x", md_value[i]);
ptr += 2;
}
ret = str;
/* Call this once before exit. */
EVP_cleanup();
return ret;
}
代码将给出正确的文件校验和有效的名称。但是一旦给出非 ascii 字符文件,程序就会失败。我使用 std::wstring 似乎解决了这个问题,但网站 here 不鼓励使用 std::wstring 说 不要在接受 UTF-16 的 API 的相邻点以外的任何地方使用 wchar_t 或 std::wstring。 如果我要遵循这一点,如何使此代码适用于所有类型的路径。我正在使用 VS2010。
【问题讨论】:
-
ifstream不需要in。它已经“进入”了。 -
是的。这是一个愚蠢的错误。
-
这似乎是一个“与接受 UTF-16 的 API 相邻的点”,所以 std::wstring 听起来不错
-
什么情况下我应该更喜欢 std::wstring 而不是 std::string ?
-
Nitpick:不要通过字符串参数选择算法,使用枚举或类似的东西。
标签: c++ visual-studio-2010 unicode