Не удается прочитать двоичные видеофайлы в GNU / Linux - PullRequest
0 голосов
/ 06 октября 2009

Я застрял с явно безвредным куском кода. Я пытаюсь прочитать весь 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 ]

3 голосов
/ 06 октября 2009

Кажется, оригинальный код правильно читает весь контент.

Проблема, по-видимому, заключается в использовании этих двоичных данных - их распечатка будет обрезаться при первом нуле, создавая впечатление, что присутствуют только 10 байтов. Вы не можете использовать какие-либо методы, предназначенные для строк или символьных массивов, для вывода двоичных данных, поскольку они усекаются с первым нулевым байтом, создавая впечатление, что массив короче, чем на самом деле.

Проверьте некоторые другие вопросы, связанные с просмотром шестнадцатеричных данных: как мне распечатать беззнаковый символ как шестнадцатеричный в c ++, используя ostream? Преобразование двоичных данных в шестнадцатеричный формат для печати

Если вы хотите добавить это к строке - в каком формате? шестигранный? 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 байт при попытке распечатать вывод?

2 голосов
/ 06 октября 2009

Функция read () в библиотеке 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. */

Обратите внимание, что большинство программистов на С делали бы это немного по-другому, вероятно, делая 'pos' указателем, который перемещается, вместо того, чтобы смещаться от 'содержимого' каждый раз в цикле. Но я подумал, что такой подход может быть более понятным.

0 голосов
/ 06 октября 2009

В случае успеха read() возвращает количество прочитанных байтов (которое может быть меньше того, о котором вы просили, и в этот момент вы должны запросить остаток.) ​​В EOF он вернет 0, а в случае ошибки вернет -1.Есть некоторые ошибки, для которых вы можете рассмотреть возможность повторного выдачи чтения (например, EINTR, которое происходит, когда вы получаете сигнал во время чтения.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...