C Язык: popen () с fread ()? - PullRequest
1 голос
/ 15 июля 2011

Я застрял на этом несколько дней, и это очень расстраивает.

Я использую popen(), чтобы вызвать процесс командной строки, получить его вывод и сохранить его в C-строке. Я использовал fgets(), но, похоже, разрывается после новой строки, поэтому я использую fread(). Единственная проблема заключается в том, что возвращаемая строка C иногда испорчена.

Вот мой код:

const char *cmd = "date";//This the shell command
char buf[BUFSIZ];//Output of the command
FILE *ptr;
int c;

if ((ptr = popen(cmd, "r")) != NULL)
     while(fread(buf, sizeof(buf),1, ptr))
          while ((c = getchar()) != EOF)
               printf("output = %s", buf);

(void) pclose(ptr);

В последней строке C иногда содержатся странные символы, которых там быть не должно, а иногда нет даже строки, доступной. Кто-нибудь может помочь? ):

Edit: вот что я делал, когда использовал fgets (). Команда Shell может быть чем угодно, что выводит текст. Не просто «свидание».


if ((ptr = popen(cmd, "r")) != NULL)<br/>while (fgets(buf, BUFSIZ, ptr) != NULL)<br/>printf("output = %s", buf);<br/>(void) pclose(ptr);

Ответы [ 4 ]

2 голосов
/ 15 июля 2011

Ну, fgets - верный способ сделать это.

FILE *ptr;

if (NULL == (ptr = popen(cmd, "r"))) {
    /* ... */
}

while(fgets(buf, sizeof(buf), ptr) != NULL) {
    /* There is stuff in 'buf' */
}

Я думаю, причина fgets не работала для вас в том, что вы делали что-то не так.

Вот почему я думаю, что у вас возникли проблемы с текущим кодом:

  • Вы не проверяете, сколько fread фактически вернулось
  • Вы читаете с getchar и отбрасывая вещи
  • У вас нет NUL терминатора в буфере

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

2 голосов
/ 15 июля 2011

Вывод date не включает символ '\0' (NUL), который необходим для правильного завершения строки. Следите за количеством прочитанных и введенных в NUL символов.

Хотя на самом деле вы должны использовать fgets, getline или аналогичные тексто-ориентированные функции для чтения из программы, такой как date. getline особенно легко (и безопасно, так как он выполняет некоторые функции управления памятью):

FILE *fp = popen("date", "r");
char *ln = NULL;
size_t len = 0;

while (getline(&ln, &len, fp) != -1)
    fputs(ln, stdout);
free(ln);
pclose(fp);
1 голос
/ 26 августа 2015

Ниже приведен правильный способ использования fread для вывода процесса с popen:

const char *cmd = "date";
char buf[BUFSIZ];
FILE *ptr;

if ((ptr = popen(cmd, "r")) != NULL) {
    /* Read one byte at a time, up to BUFSIZ - 1 bytes, the last byte will be used for null termination. */
    size_t byte_count = fread(buf, 1, BUFSIZ - 1, ptr);
    /* Apply null termination so that the read bytes can be treated as a string. */
    buf[byte_count] = 0;
    printf("%s\n", buf);
}

(void) pclose(ptr);

Как видите, основная проблема заключается в правильном обращении с нулевым завершением. Параметр двух размеров fread также важен, вы должны позволить ему читать символ за символом. Обратите внимание, что в случае popen, fread вернет 0, только если процесс завершился без каких-либо выходных данных. не вернет 0, если процессу потребуется много времени для печати чего-либо.

Если выходной сигнал больше BUFSIZ, вы можете обернуть fread петлей while.

1 голос
/ 15 июля 2011

fread не вставляет терминатор NUL после того, что он читает.Вам нужно проверить возвращаемое значение, чтобы узнать, сколько оно прочитано, и только напечатать столько.Если вы читаете с fread, вы обычно хотите записать данные с fwrite, что-то в следующем порядке:

long bytes;
while ((bytes=fread(buf, sizeof(buf), 1, ptr))>0)
    fwrite(buf, bytes, 1, stdout);
...