【问题标题】:Windows API base64 encode/decodWindows API base64 编码/解码
【发布时间】:2016-12-03 05:45:26
【问题描述】:

我想base64一个大文件(500MB)

我使用this code,但它不适用于大文件

我测试了 CryptStringToBinary,但它也不起作用

我该怎么办????

【问题讨论】:

  • 将您的应用程序编译为 64 位应用程序。该代码和CryptStringToBinary 都可能需要 500MB 内存来保存最终字符串。 32 位应用程序很可能不会发生这种情况。
  • @PaulMcKenzie 可以,但是我的老师不允许我们更改设置,我们应该使用默认设置进行此操作
  • 告诉你的老师你不会表演魔术。如果您要使用这些函数,并且必须生成 500MB 以上的字符串,那么使用 32 位应用程序就不会轻易发生这种情况。即使您勉强过活,您也已经用尽了大量内存,您的应用程序可能会由于内存耗尽而在其他地方崩溃。唯一要建议的是找到一个在生成 base64 编码/解码时将数据写入磁盘的实现,而不是基于字符串。
  • 是否可以通过ReadFile函数逐块读取文件,然后base64块,并读取第二块......?
  • 您可以获取链接到的原始代码并将目标更改为文件流。然后将字节写入文件流 --- 换句话说,pDst 需要更改。

标签: c++ api encoding base64 decoding


【解决方案1】:

问题显然是在 32 位应用程序中没有足够的内存来存储 500 兆字节的字符串。

this link 提到了一种解决方案,它将数据写入字符串。假设代码正常工作,调整它以写入文件流并不难。

#include <windows.h>
#include <fstream>

static const wchar_t *Base64Digits = L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

int Base64Encode(const BYTE* pSrc, int nLenSrc, std::wostream& pDstStrm, int nLenDst)
{
    wchar_t pDst[4];
    int nLenOut = 0;

    while (nLenSrc > 0) {
        if (nLenDst < 4) return(0); 
        int len = 0;
        BYTE s1 = pSrc[len++];
        BYTE s2 = (nLenSrc > 1) ? pSrc[len++] : 0;
        BYTE s3 = (nLenSrc > 2) ? pSrc[len++] : 0;
        pSrc += len;
        nLenSrc -= len;

        //------------------ lookup the right digits for output
        pDst[0] = Base64Digits[(s1 >> 2) & 0x3F];
        pDst[1] = Base64Digits[(((s1 & 0x3) << 4) | ((s2 >> 4) & 0xF)) & 0x3F];
        pDst[2] = Base64Digits[(((s2 & 0xF) << 2) | ((s3 >> 6) & 0x3)) & 0x3F];
        pDst[3] = Base64Digits[s3 & 0x3F];

        //--------- end of input handling
        if (len < 3) {  // less than 24 src bits encoded, pad with '='
            pDst[3] = L'=';
            if (len == 1)
                pDst[2] = L'=';
        }

        nLenOut += 4;

        // write the data to a file
        pDstStrm.write(pDst,4);

        nLenDst -= 4;
    }

    if (nLenDst > 0) *pDst = 0;

    return (nLenOut);
}

所做的唯一更改是将 4 个字节写入宽流,而不是将数据附加到字符串

这是一个示例调用:

int main()
{
    std::wofstream ofs(L"testfile.out");
    Base64Encode((BYTE*)"This is a test", strlen("This is a test"), ofs, 1000);
}

上面生成一个带有base64字符串VGhpcyBpcyBhIHRlc3Q=的文件,解码后生成This is a test

注意参数是std::wostream,这意味着任何宽输出流类(如std::wostringstream)也可以工作。

【讨论】:

  • 谢谢,它有效,但这不是我想要的。 - 是否可以用setfilepointer 更改指针并从第二个块读取文件?
  • 32 位允许寻址高达 2^32 字节,即 4 GB,500 MB 仅为 0.5 GB。假设 wchar_t 是 2 字节,最多可达 1.5 GB。有趣的是,尽管您说 500 MB 太多了,但您的解决方案仍然需要 500 MB 内存块,而不是额外的 1 GB 用于目标
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多