从磁盘读取映像文件时出错

时间:2013-06-14 08:53:21

标签: c++ c image fread

我正在尝试从磁盘读取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字符放入图像缓冲区?

5 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:2)

您不能将strlen用于非字符串的内容。您应该从readIamge函数返回大小。 e.g。

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

如果使用C ++编程,则应该返回一种图像类的实例。这样可以避免结果的分散位置。

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

答案 2 :(得分: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数据&amp;它的实际大小。 如果您不介意使用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);

答案 3 :(得分: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 ++构造,标准库来改进您的代码。

答案 4 :(得分:0)

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