【问题标题】:Base64 image file encoding with C++使用 C++ 进行 Base64 图像文件编码
【发布时间】:2018-03-28 18:08:39
【问题描述】:

我正在编写一些简单的代码来将文件编码为 base64。我有一个简短的 c++ 代码,可以将文件读入向量并将其转换为 unsigned char*。我这样做是为了正确使用我得到的编码功能。

问题:它适用于(不同大小的)文本文件,但不适用于图像文件。我不知道为什么。什么给了?

对于包含文本 abcd 的简单 text.txt,我的代码和 bash $( base64 text.txt ) 的输出是相同的。

另一方面,当我输入图像时,输出类似于iVBORwOKGgoAAAAAAA......AAA== 或有时以corrupted size vs prev_size Aborted (core dumped) 结尾,前几个字节是正确的。

代码:

static std::vector<char> readBytes(char const* filename)
{
    std::ifstream ifs(filename, std::ios::binary|std::ios::ate);
    std::ifstream::pos_type pos = ifs.tellg();
    std::vector<char> result(pos);
    ifs.seekg(0, std::ios::beg);
    ifs.read(&result[0], pos);

    return result;
}

static char Base64Digits[] =
 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

int ToBase64Simple( const BYTE* pSrc, int nLenSrc, char* pDst, int nLenDst )
{
   int nLenOut= 0;
   while ( nLenSrc > 0 ) {

      if (nLenOut+4 > nLenDst) {
      cout << "error\n";
      return(0); // error
      }

      // read three source bytes (24 bits)
      BYTE s1= pSrc[0];   // (but avoid reading past the end)
      BYTE s2= 0; if (nLenSrc>1) s2=pSrc[1]; //------ corrected, thanks to  jprichey
      BYTE s3= 0; if (nLenSrc>2) s3=pSrc[2];

      DWORD n;
      n =  s1;    // xxx1
      n <<= 8;    // xx1x
      n |= s2;    // xx12
      n <<= 8;    // x12x
      n |= s3;    // x123

      //-------------- get four 6-bit values for lookups
      BYTE m4= n & 0x3f;  n >>= 6;
      BYTE m3= n & 0x3f;  n >>= 6;
      BYTE m2= n & 0x3f;  n >>= 6;
      BYTE m1= n & 0x3f;

      //------------------ lookup the right digits for output
      BYTE b1 = Base64Digits[m1];
      BYTE b2 = Base64Digits[m2];
      BYTE b3 = Base64Digits[m3];
      BYTE b4 = Base64Digits[m4];

      //--------- end of input handling
      *pDst++ = b1;
      *pDst++ = b2;
      if ( nLenSrc >= 3 ) {  // 24 src bits left to encode, output xxxx
         *pDst++ = b3;
         *pDst++ = b4;
      }
      if ( nLenSrc == 2 ) {  // 16 src bits left to encode, output xxx=
         *pDst++ = b3;
         *pDst++ = '=';
         }
      if ( nLenSrc == 1 ) {  // 8 src bits left to encode, output xx==
         *pDst++ = '=';
         *pDst++ = '=';
      }
      pSrc    += 3;
      nLenSrc -= 3;
      nLenOut += 4;
   }
   // Could optionally append a NULL byte like so:
   *pDst++= 0; nLenOut++;
   return( nLenOut );
}

int main(int argc, char* argv[])
{
    std::vector<char> mymsg;
    mymsg = readBytes(argv[1]);
    char* arr = &mymsg[0];
    int len = mymsg.size();
    int lendst = ((len+2)/3)*4;
    unsigned char* uarr = (unsigned char *) malloc(len*sizeof(unsigned char));
    char* dst = (char *) malloc(lendst*sizeof(char));;
    mymsg.clear(); //free()

    // convert to unsigned char
    strncpy((char*)uarr, arr, len);

    int lenOut = ToBase64Simple(uarr, len, dst, lendst);
    free(uarr);

    int cont = 0;
    while (cont < lenOut) //(dst[cont] != 0)
        cout << dst[cont++];
    cout << "\n";
}

欢迎任何见解。

【问题讨论】:

  • 应用标签前请阅读说明。您应用的“c”标签明确提到将其与 C++ 结合通常是错误的,并且还给出了原因。
  • 听起来您需要指定您正在读取二进制文件而不是文本文件。在写入/读取/访问时,它们的处理方式不同。

标签: c++ image encoding base64


【解决方案1】:

我发现了两个问题。

首先,您要在使用完 mymsg 向量之前清除它。这使得arr 指针悬空(指向不再分配的内存)。当您访问 arr 以获取数据时,您最终会出现未定义的行为。

然后您使用strncpy 复制(可能)二进制数据。此复制将在到达文件中的第一个 nul (0) 字节时停止,因此不会复制所有数据。你应该改用memcpy

【讨论】:

  • arr 指向相同的数据,即使在 mymsg.clear() 之后,只要这些数据仍然存在,它就可以工作。另一方面,使用 memcpy 解决了这个问题。我没有意识到 strncpy 会停在一个空值上,这很有意义。谢谢。
猜你喜欢
  • 2011-04-12
  • 1970-01-01
  • 2018-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-06
  • 1970-01-01
相关资源
最近更新 更多