Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/visual-studio-2010/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用非ASCII字符打开文件_C++_Visual Studio 2010_Unicode - Fatal编程技术网

C++ 使用非ASCII字符打开文件

C++ 使用非ASCII字符打开文件,c++,visual-studio-2010,unicode,C++,Visual Studio 2010,Unicode,我正在尝试计算文件的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; s

我正在尝试计算文件的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;
}
#包括
#包括
#包括
#包括
#包括
#包括
const int MAX_BUFFER_SIZE=1024;
std::string文件校验和(std::string,std::string);
长整型GetFileSize(标准::字符串文件名)
{
结构stat64 stat buf;
int rc=_stat64(filename.c_str(),&stat_buf);
返回rc==0?统计数据大小:-1;
}
std::string fname=“D:\\Private\\Test\\asdf.txt”;//需要支持此D:\\Private\\Test\\सर्वज्ञ पन्त.文本
int main()
{
std::string checksum=FileChecksum(fname,“sha256”);

std::cout
wchar\u t
不能跨多个平台移植,因为它在某些平台(Windows)上是2字节(UTF-16),但在其他平台(Linux等)上是4字节(UTF-32)。这就是警告您的内容

在您的特定情况下,您只关注Windows,因此使用
std::wstring
非常好,因为它使用UTF-16,这与Win32 API在所有地方使用的编码相同。您正在寻找的是Microsoft的
\wstat64()
函数,以及接受
wchar\t*
文件名的Microsoft非标准
std::ifstream
构造函数:

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;
}

也就是说,您的
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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
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::对于
ifstream
,您是否不需要
in
。它是“in”区域是的。这是一个愚蠢的错误。这似乎是一个“与接受UTF-16的API相邻的点”,所以std::wstring听起来不错。什么情况下我应该更喜欢std::wstring而不是std::string?吹毛求疵:不要按字符串参数选择算法,使用枚举或类似的东西。do不一定要跟随一段时间。while似乎缺少。我必须这样做使此代码跨平台。该代码应在windows和linux中获取文件的校验和。是的,它在
时丢失了一个
,我现在已经修复了它。不幸的是,不同的平台以不同的编码处理不同的文件路径(windows使用UTF-16,*Nix使用UTF-8等),不同的格式,等等。因此,您必须使用
#ifdef
语句中包装的一些特定于平台的代码来说明这一点,除非您使用已经为您提供了该功能的第三方库。代码无法计算正确的校验和。在调试器下运行时,代码会将文件数据读入缓冲区,并且如果内容s小于缓冲区的大小,缓冲区中有剩余。例如,由于没有终止字符,所以像
sdasÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ
返回缓冲区中的实际字节数,方法是
read
。缓冲区中没有剩余传递给
EVP\u DigestUpdate()
。至于
返回true,我忘记了
read()
在达到EOF时设置
failbit
eofbit
。我已经更新了代码以说明这一点。代码现在似乎正常工作,但现在计算错误的校验和。它确实支持非ascii路径,但计算的SHA-256是错误的。
#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;
}