1

我想用 C++ 解码一个大文件的字符串。

链的大小为:1827500 个字符,文件为:1370626 个字节

我的问题是解码功能不起作用。解码后的文件与原始文件不同。

以下是我尝试过的两种方法

第一的 :

char  *base64_decode(const std::string &input, long *size)
{
    BIO *p_bio_mem = nullptr;
    BIO *p_bio_b64 = nullptr;
    char *retrnvalue;

    p_bio_b64 = BIO_new(BIO_f_base64());
    if (!p_bio_b64) { throw std::runtime_error("BIO_new failed"); }
    BIO_set_flags(p_bio_b64, BIO_FLAGS_BASE64_NO_NL); //Don't require trailing newlines

    p_bio_mem = BIO_new_mem_buf((void*)input.c_str(), input.length());
    if (!p_bio_mem) { throw std::runtime_error("BIO_new failed"); }
    BIO_push(p_bio_b64, p_bio_mem);

    // read result from chain
    // read sequence (reverse to write): buf <<-- p_bio_b64 <<-- p_bio_mem
    std::vector<char> buf((input.size() * 3 / 4) + 1);
    std::string result;
    for (;;)
    {
        auto nread = BIO_read(p_bio_b64, buf.data(), buf.size());
        if (nread < 0) { return NULL; //fail}
        if (nread == 0) { break; } // eof
        result.append(buf.data(), nread);
    }

    BIO_free_all(p_bio_b64);
    *size = buf.size();
    retrnvalue = new char[*size];
    memcpy(retrnvalue, buf.data(), *size);

    return retrnvalue;
}

第二:

来自这里的代码:如何在 C 中进行 base64 编码(解码)?

有些行尾不同:

与 WinMerge 的差异

但不是整个文件:

WinMerge diff 的左侧可视化器

你能告诉我为什么吗?和/或告诉我另一种编码文件以便于传输的方法?

我有这个输入:drive.google.com/file/d/0B1i4Ez8N86wFblJnaFF6YVNVTWs/view

我想要这个输出:drive.google.com/file/d/0B1i4Ez8N86wFdl9OUE5UMFB3R28/view

(对不起,我不能放超过 2 个链接)

PS:当我使用“certutil -decode”批量解码时,它可以正常工作。

已解决:问题已解决,问题是 fwrite 。使用 ofstream 写入功能修复

4

2 回答 2

1

您读取 base64 数据的代码非常混乱:

std::vector<char> buf((input.size() * 3 / 4) + 1);
std::string result;
for (;;)
{
    auto nread = BIO_read(p_bio_b64, buf.data(), buf.size());
    if (nread < 0) { return NULL; } //fail
    if (nread == 0) { break; } // eof
    result.append(buf.data(), nread);
}

BIO_free_all(p_bio_b64);
*size = buf.size();
retrnvalue = new char[*size];
memcpy(retrnvalue, buf.data(), *size);

return retrnvalue;

您将数据读入一个名为 的字符串result中,但您从未对它做任何事情。然后将暂存缓冲区的内容复制到输出缓冲区中。您也可以取消size指针,只返回 astd::string而不是 raw char*

另一个可能的问题是线路

BIO_set_flags(p_bio_b64, BIO_FLAGS_BASE64_NO_NL); //Don't require trailing newlines

如果您的输入确实包含换行符,那么该行将导致问题。如果您想使用可能包含或不包含换行符的输入,则需要将该行设置为有条件的:

if (input.find('\n') == std::string::npos) {
    BIO_set_flags(p_bio_b64, BIO_FLAGS_BASE64_NO_NL); //Don't require trailing newlines
}

总之,看起来像这样:

std::string base64_decode(const std::string &input)
{
    BIO *p_bio_mem = nullptr;
    BIO *p_bio_b64 = nullptr;

    p_bio_b64 = BIO_new(BIO_f_base64());
    if (!p_bio_b64) { throw std::runtime_error("BIO_new failed"); }
    if (input.find('\n') == std::string::npos) {
        BIO_set_flags(p_bio_b64, BIO_FLAGS_BASE64_NO_NL); //Don't require trailing newlines
    }

    p_bio_mem = BIO_new_mem_buf((void*)input.c_str(), input.length());
    if (!p_bio_mem) { throw std::runtime_error("BIO_new failed"); }
    BIO_push(p_bio_b64, p_bio_mem);

    std::stringstream result;
    std::vector<char> buf(1024);
    while (auto nread = BIO_read(p_bio_b64, buf.data(), buf.size()))
    {
        if (nread < 0) { throw std::runtime_error("OMGZ"); } //fail
        result.write(buf.data(), nread);
    }

    BIO_free_all(p_bio_b64);
    return result.str();
}

现场演示

您可能还希望添加一些错误处理以在出现错误时清理您的BIO实例(例如在您链接到的答案中),但这不是导致错误结果的原因。

于 2016-08-27T00:26:36.633 回答
0

已解决:问题已解决,问题是 fwrite 。使用 ofstream 写入功能修复

于 2016-08-31T23:02:26.723 回答