1

我正在尝试从磁盘读取 jpg 文件,然后复制到 char 缓冲区。问题是字节上有一些 NULL 字符,当我读取 char 缓冲区时遇到问题。这是当前代码:

char* readImg(char* filename)
{
    FILE * pFile;
    char jpgBuffer[20048];
    long lSize;
    errno_t result = fopen_s (&pFile,filename,"rb");
    if (result != 0) {
        printf("Error \n");
    }

    fseek (pFile , 0 , SEEK_END);
    lSize = ftell (pFile);
    rewind (pFile);

    result = fread (jpgBuffer,1,lSize,pFile);
    fclose (pFile);

    jpgBuffer[lSize] = '\0';
    return jpgBuffer;
}

并且对该函数的调用是:

char* img = readImg("img.jpg");

然后,我需要编码成base64,但如果我想用strlen() 知道图像缓冲区的大小,我得到的大小是4,因为5 个字符是“0”。

如何避免 NULL 字符进入图像缓冲区?

4

5 回答 5

2

你可以改变你的函数原型。

long readImage(const char* filename, char* buf, long bufSize)
{
    FILE * pFile;
    long lSize;
    errno_t result = fopen_s (&pFile,filename,"rb");
    if (result != 0) {
        printf("Error \n");
    }

    fseek (pFile , 0 , SEEK_END);
    lSize = ftell (pFile);
    rewind (pFile);

    if(bufSize < lSize)
    {
        printf("buf too small, needs %lu\n", lSize);
        fclose(pFile);
        return -1;
    }

    result = fread (buf,1,lSize,pFile);
    fclose (pFile);

    return lSize;
}

然后你会得到 img 数据和它的实际大小。如果您不介意使用 malloc,您可以在函数中为缓冲区分配内存。

long readImage(const char* filename, char** pbuf)
{
    FILE * pFile;
    long lSize;
    errno_t result = fopen_s (&pFile,filename,"rb");
    if (result != 0) {
        printf("Error \n");
    }

    fseek (pFile , 0 , SEEK_END);
    lSize = ftell (pFile);
    rewind (pFile);

    *pbuf = (char*)malloc(lSize * sizeof(char));
    result = fread (*buf,1,lSize,pFile);
    fclose (pFile);

    return lSize;
}

像下面这样调用这个函数,你需要记住空闲缓冲区。

char* buf = NULL;
long len = 0;

len = readImage(filename, &buf);

...

free(buf);
于 2013-06-14T09:04:16.723 回答
2

使用lSize您确定readImg(...)的文件大小。strlen用于以空结尾的字符串。不用于strlen确定图像大小(以字节为单位)。

另请注意,您应该通过使用字节大小将其分配jpgBuffer为堆变量。这样你就可以返回一个指向堆内存的指针。函数返回后,您当前的堆栈变量将无效,因此指向它的指针也将无效。这样,您也不必担心需要比硬编码值更多字节的情况(您目前不检查!)。new[]lSizejpgBuffer

您还需要lSize通过输入参数指针/引用变量返回 ,这样您就可以在以后进行迭代。

于 2013-06-14T08:57:26.773 回答
2

你不能使用strlen不是字符串的东西。您应该从readIamge函数返回大小。例如

char* readImg(char* filename, int *size);

如果你用 C++ 编程,你应该返回一个图像类的实例。这将避免结果的飞溅位置。

此外,您永远不应该将局部变量的地址作为 jpgBuffer 返回。从函数返回后,该变量将被覆盖。

于 2013-06-14T08:58:07.780 回答
1

char*您可以在没有任何大小信息的情况下返回您的数据。

你不能返回你的jpgBuffer, 本地分配的。

将您的功能更改为:

int readImg(char* filename, unsigned char* buffer)
{ 
  //...
  result = fread (buffer,1,lSize,pFile);

  return lSize;
}

如果可以,请在调用函数中分配缓冲区,这将简化您的代码。但是,如果您想避免缓冲区溢出,您应该将分配的缓冲区的大小传递给您的读取函数,如果文件大小大于您分配的大小,则返回错误/抛出异常。

int readImg(char* filename, unsigned char* buffer, size_t aSize)
{ 
  //...
  fseek (pFile , 0 , SEEK_END);
  lSize = ftell (pFile);
  if (lSize > aSize)
  {
    // Manage error case
  }
  //...
  result = fread (buffer,1,lSize,pFile);

  return lSize;
}

请记住,这种编码方式更像是 C 风格而不是 C++ 风格。如果您希望并且可以使用 C++,请利用 C++ 结构和标准库来改进您的代码。

于 2013-06-14T08:58:16.920 回答
0

jpgBuffer是“二进制”缓冲区,而不是“字符串”。最后放一个空字符是无意义的。您应该使用该result变量来读取缓冲区。

于 2013-06-14T08:58:03.797 回答