C语言中read()和fgets()的区别

13

我想从stdin流中读取数据。使用read()或fgets()从stdin流中读取是否有任何区别?

我附上了使用fgets和read的两段代码。 使用fgets,我可以轻松地使用Java程序编写并从C程序读取。 使用read和write,我的Java程序挂起等待来自未到达的C程序输出。

我只是读取一行将其保留在buf中并添加A。

Java程序能够与以下使用fgets和puts的程序通信。

#include <stdio.h>
#include <string.h>
#define SIZE  200000
main()
{
int rc;
int df;
int i;
char buf[SIZE];
for(i=0;i<=120000;i++) {
      memset(buf,'\0',SIZE);
      if(!fgets(buf,SIZE-1,stdin))
        continue;
      strcat(buf,"A_A_A_A_A_A_A");
      puts(buf);
}

但不适用于read()和write()函数

main()
{
int rc;
int df;
int i;
char buf[32768];
rc = fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
//rc = fcntl(fileno(stdout), F_SETFL, O_NONBLOCK);
FILE *fp;
for (;;) 
{
    int rc=-1;
    memset(buf,'\0',32768);
    //rc = fread(buf,5, 1, stdin);
    rc = read(fileno(stdin),buf,32768); 
    if (rc > 0)
    {
        strcat(buf,"B_B_B_B_B_B_B_B_B");
        write(fileno(stdout),buf,strlen(buf));

    }
}

}

有人能说一下原因吗?我仍然很难弄清楚。


@DarkDust他只有7个问题,还不算太糟糕 :-) - cnicutar
1
@cnicutar:考虑到他的两个问题已经半年没回复了,而其他问题也是三四月份的,这确实很糟糕。 - DarkDust
嘿,对不起,我不知道有一种机制可以接受答案。我会去做的。 - ssD
5个回答

34
  • fgets 是一个函数,read 是一个系统调用
  • fgets 是标准 C,read 不是
  • fgets 是 stdio 缓冲的,read 不是
  • fgets 使用 FILE *read 使用文件描述符
  • fgets 读取到换行符,read 读取你要求它读取的数量

6
fgets()函数将一个空字节追加到缓冲区(这使strcat()有一个起始位置);而read()函数则不会。 - user207421

9

有一个重要的替代方法(fread),它位于中间位置,因此问题实际上应该分为两个部分——这两个部分在SO中已经得到了很好的回答:

什么是 freadread 的区别

什么是 fgetsfread 的区别

快速准则:如果您打算逐行读取文本数据,请使用fgets,否则请使用fread


3
#include <stdio.h>
char    fgets (char * restrict str, int size, FILE * restrict stream)
fgets()函数从给定的流中读取最多比size指定的字符数少一个字符,并将它们存储在字符串str中。当找到换行符、文件末尾或错误时,读取停止。
参考:fgets()
#include <unistd.h>
ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset);
read()函数将尝试从与打开的文件描述符fildes相关联的文件中读取nbyte字节到指向buf的缓冲区中。在同一管道、FIFO或终端设备上进行多个并发读取的行为是未指定的。
参考:read()

+1 @Andrei 对于 opengroup(而不是 cplusplus)非常赞赏...但您可以使用 POSIX.1-2008 参考 而不是您链接中的 POSIX.1-2004 ;) - pmg
更新的参考链接,请@pmg查看。谢谢您纠正我的答案。 - Andrei Sfat
@Andrei...根据上述程序,我无法区分使用fgets从stdin读取还是使用read读取stdin的区别。同样,puts(buf)帮助我通过外部程序从stdout读取,write(stdout,buf)也是如此。但是,相对于read和write而言,puts和gets较慢,并且puts和gets可以与外部Java程序一起使用...您能帮忙澄清这一点吗? - ssD
@ssD,你是如何从Java中调用C程序的? - Andrei Sfat
@Andrei 我正在使用 Process.getruntime(),然后使用 BufferedWriter 和 BufferedReader 在外部 C 程序中进行读写。 - ssD
@ssD,你尝试过使用JNI(Java Native Interface)吗?http://java.sun.com/docs/books/jni/html/jniTOC.html。也许在从Java中调用C系统调用方面存在一些问题。尝试使用JNI,也许会有所帮助。 - Andrei Sfat

1

其中一个函数 (read) 尝试读取指定数量的字节,而另一个函数 (fgets) 尝试读取一行并在遇到换行符时停止。


1
这两个函数没有任何共同点。read是一个POSIX系统调用,它从文件句柄中读取数据。fgets是一个C库函数,它从FILE *中读取数据。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接