gpt4 book ai didi

c++ - 打开包含非 ASCII 字符的文件

转载 作者:行者123 更新时间:2023-11-30 05:42:55 30 4
gpt4 key购买 nike

我正在尝试计算文件的 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 字 rune 件,程序就会失败。我使用了 std::wstring,它似乎解决了这个问题,但网站 here不鼓励使用 std::wstring不要在除了接受 UTF-16 的 API 的相邻点以外的任何地方使用 wchar_t 或 std::wstring。/strong> 如果我要遵循这个,我如何让这个代码适用于所有类型的路径。我正在使用 VS2010。

最佳答案

wchar_t 不可跨多个平台移植,因为它在某些平台 (Windows) 上是 2 字节 (UTF-16),但在其他平台(Linux 等)上是 4 字节 (UTF-32) ).那就是site正在警告你。

在您的特定情况下,您只关注 Windows,因此 std::wstring 使用起来非常好,因为它使用 UTF-16,这与 Win32 API 使用的编码相同到处都是。您正在寻找的是 Microsoft 的 _wstat64() 函数,以及 Microsoft 的非标准 std::ifstream 接受 wchar_t* 文件名的构造函数:

long long int GetFileSize(std::wstring filename)
{
struct _stat64 stat_buf;
int rc = _wstat64(filename.c_str(), &stat_buf);
return rc == 0 ? stat_buf.st_size : -1;
}

std::wstring file_path = L"D:\\Private\\Test\\सर्वज्ञ पन्त.txt";

...

static std::string FileChecksum(std::wstring file_path, std::string algorithm="sha256")
{
...
std::ifstream readfile(file_path.c_str(), std::ifstream::binary);
...
}

也就是说,您的 FileChecksum() 函数比它需要的更复杂,如果发生错误,它不会正确清理,它不会验证 std::ifstream::read() 实际上正在读取您请求的字节数(它可能读取的更少),并且它滥用了 std::ifstream::eof()

尝试更像这样的东西:

#include <openssl\evp.h>
#include <sys\stat.h>
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <iomanip>

const int MAX_BUFFER_SIZE = 1024;
std::string FileChecksum(std::wstring file_path, std::string algorithm = "sha256");

std::wstring fname = L"D:\\Private\\Test\\सर्वज्ञ पन्त.txt";

int main()
{
std::string checksum = FileChecksum(fname, "sha256");
std::cout << checksum << std::endl;
return 0;
}

std::string FileChecksum(std::wstring file_path, std::string algorithm)
{
EVP_MD_CTX *mdctx = NULL;
const EVP_MD *md;
unsigned char md_value[EVP_MAX_MD_SIZE];
char buffer[MAX_BUFFER_SIZE];
unsigned int md_len;
std::ostringstream oss;
std::string ret;

std::ifstream readfile(file_path.c_str(), std::ifstream::binary);
if (readfile.fail())
{
std::cout << "Could not open file\n";
goto finished;
}

OpenSSL_add_all_digests();

md = EVP_get_digestbyname(algorithm.c_str());
if (!md) {
std::cout << "Unknown message digest " << algorithm << "\n";
goto cleanup;
}

mdctx = EVP_MD_CTX_create();
if (!mdctx) {
std::cout << "Could not create context for message digest " << algorithm << "\n";
goto cleanup;
}

EVP_DigestInit_ex(mdctx, md, NULL);

do
{
readfile.read(buffer, sizeof(buffer));
if ((readfile.fail()) && (!readfile.eof()))
{
std::cout << "Could not read from file\n";
goto cleanup;
}

EVP_DigestUpdate(mdctx, buffer, readfile.gcount());
}
while (!readfile.eof());

EVP_DigestFinal_ex(mdctx, md_value, &md_len);

for(unsigned int i = 0; i < md_len; i++)
oss << std::hex << std::setw(2) << std::setfill('0') << (int) md_value[i];
ret = oss.str();

cleanup:
if (mdctx) EVP_MD_CTX_destroy(mdctx);
EVP_cleanup();

finished:
return ret;
}

关于c++ - 打开包含非 ASCII 字符的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30454875/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com