Функция ftell, дающая -1 в C для стандартного вывода - PullRequest
1 голос
/ 09 октября 2011

Я хочу wget в C, и я использую popen для этого.

FILE *stdoutPtr = popen(command,"r");
fseek(stdoutPtr, 0L, SEEK_END);
long pos = ftell(stdoutPtr);

Здесь я хочу получить размер stdout, чтобы я мог инициализировать буфер. Но pos переменная всегда равна -1. pos должен сообщить мне текущую позицию указателя чтения.

Пожалуйста, помогите ....

Ответы [ 2 ]

6 голосов
/ 09 октября 2011

FILE, возвращаемое popen, - это не обычный файл, а вещь, называемая pipe.(Это то, что означает p.) Потоки данных через передаются по каналу от stdout команды, которую вы вызывали в своей программе.Поскольку это канал связи, а не файл на диске, канал не имеет определенного размера, и вы не можете искать разные места в потоке данных.Следовательно, fseek и ftell оба не пройдут при применении к этому FILE, и именно это означает возвращаемое значение -1.Если вы проверите errno сразу после вызова ftell, вы обнаружите, что он имеет значение ESPIPE, что означает «Вы не можете сделать это с каналом».

Если выпытаясь прочитать все выходные данные команды в один буфер char*, единственный способ сделать это - повторно вызывать одну из функций чтения, пока она не покажет конец файла, и при необходимости увеличить буфер, используя realloc.Если выходные данные потенциально велики, было бы лучше изменить вашу программу для обработки данных кусками, если есть какой-либо способ сделать это.

1 голос
/ 09 октября 2011

Вы не можете использовать трубы таким образом. Прежде всего, информация устареет, как только вы ее получите, так как к тому времени в канал можно будет записать больше данных. Вы должны использовать другую стратегию распределения.

Самая распространенная стратегия - выделить буфер фиксированного размера и просто продолжать чтение, пока не дойдете до конца файла. Вы можете обрабатывать данные так, как вы их читаете, если хотите.

Если вам нужно обработать все данные в одном блоке, вы можете выделить большой буфер и начать чтение в него. Если он заполнится, используйте realloc для увеличения буфера и продолжайте, пока у вас все не будет.

Распространенным шаблоном является сохранение указателя буфера, количества буферов и размера выделения. Первоначально установите размер выделения, скажем, 64K. Установите счетчик на ноль. Выделите буфер 64 КБ. Считайте до size-count байтов в буфер. Если вы нажмете EOF, остановитесь. Если буфер почти заполнен, увеличьте размер выделения на 50% и realloc буфер.

...