无法读取GNU / Linux中的二进制视频文件

时间:2009-10-06 15:45:38

标签: c linux file

我遇到了一条看似无害的代码。我正在尝试将整个flv视频文件读入uint8_t数组,但是没有理由只读取10个第一个字节。

contents = malloc(size + 1);

if (read(fd, contents, size) < 0)
{
    free(contents);
    log_message(WARNING, __func__, EMSG_READFILE);
    return (NULL);
}

我也尝试过fopen和“rb”,但似乎Glibc忽略了额外的'b'或其他东西。有线索吗?

提前致谢。

编辑:也许它会读取EOF字符?

PS。 'size'是一个包含使用stat()的实际文件大小的变量。

3 个答案:

答案 0 :(得分:3)

原始代码似乎正确地读取了整个内容。

问题似乎在于使用二进制数据 - 将其打印出来将在第一个空值处截断,使其看起来只有10个字节。 您不能使用任何用于字符串或字符数组的方法来输出二进制数据,因为它们将在第一个空字节处截断,使得数组看起来比实际更短。

查看与查看十六进制数据相关的其他一些问题: how do I print an unsigned char as hex in c++ using ostream? Converting binary data to printable hex

如果要将其附加到字符串 - 以什么格式?十六进制? BASE64?原始字节不起作用。

这是我发布的原始代码。一些小的改进,加上一些更好的诊断代码:

int ret, size = 4096; /* Probably needs to be much bigger */
uint8_t *contents;
contents = malloc(size + 1);

if(contents == NULL)
{
    log_message(WARNING, __func__, EMSG_MEMORY);
    return (NULL);
}

ret = read(fd, contents, size);
if(ret < 0)
{
    /* Error reading file */
    free(contents);
    log_message(WARNING, __func__, EMSG_READFILE);
    return (NULL);
}

for(i = 0;i < ret;++i)
{
    printf("%c", contents[i]);
    /* printf("%0.2X", (char) contents[i]); /* Alternatively, print in hex */
}

现在,真的是10?或者,当您尝试打印输出时,您只获得10个字节吗?

答案 1 :(得分:2)

C库中的'read()'函数不一定会一次性返回整个读取。事实上,如果您正在阅读非常多的数据,通常不会在一次通话中将其提供给您。

对此的解决方案是在循环中调用read(),继续询问更多数据,直到获得所有数据,或者直到读取返回错误,由负返回值指示,或者结束 - 文件,由零返回值表示。

类似以下内容(未经测试):

contents = malloc(size + 1);

bytesread = 0;
pos = 0;
while (pos < size && (bytesread = read(fd, contents + pos, size - pos)) > 0)
{
    pos += bytesread;
}

if (bytesread < 0)
{
    free(contents);
    log_message(WARNING, __func__, EMSG_READFILE);
    return (NULL);
}

/* Go on to use 'contents' now, since it's been filled.  Should probably 
   check that pos == size to make sure the file was the size you expected. */

请注意,大多数C程序员会这样做的方式稍有不同,可能会使'pos'成为一个随时移动的指针,而不是每次都通过循环从'contents'中偏移。但我认为这种方法可能更清楚。

答案 2 :(得分:0)

成功时,read()返回读取的字节数(可能小于您要求的字节数,此时您应该要求其余的。)在EOF上它将返回0并且出错时它将返回-1。您可能需要考虑重新发出读取的一些错误(例如,在读取期间收到信号时发生的EINTR。)