C 语言:popen() 和 fread()?

问题描述 投票:0回答:4

我已经在这个问题上坚持了几天了,这真的很令人沮丧。

我正在使用

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 字符串有时会包含不应该存在的奇怪字符,或者有时甚至没有可用的字符串。有人可以帮忙吗? ):

编辑:这是我在使用 fgets() 时所做的事情。 Shell 命令可以是任何输出文本的命令。不仅仅是“约会”。


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

c popen fread
4个回答
4
投票

fread
不会在读取的内容后插入 NUL 终止符。您需要检查返回值以了解读取了多少内容,并且仅打印该内容。如果您使用
fread
进行读取,您通常希望使用
fwrite
写入数据,按以下顺序:

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

3
投票

嗯,

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
合法地阅读的内容可能比你告诉的少


3
投票

以下是使用

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
的两个大小参数也很重要,你必须让它一个字符一个字符地读取(意味着
fread
的第二个参数必须为1)。

请注意,在

popen
的情况下,如果进程退出且没有给出任何输出,则
fread
只会返回 0。如果进程需要很长时间才能打印任何内容,它不会返回 0。

如果输出大于

BUFSIZ

,您可以用 
fread
 循环包裹 
while


2
投票

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);
    
© www.soinside.com 2019 - 2024. All rights reserved.