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