fread和fgets的规格之间的区别?

时间:2019-04-20 23:07:25

标签: c fgets fread

从文件读入时,fread和fgets有什么区别? 我使用相同的fwrite语句,但是当我使用fgets读取.txt文件时,它可以按预期工作,但是当我使用fread()时,它却不能工作。

从文件读取和读取文件时,我已从fgets / fputs切换为fread / fwrite。我用fopen(rb / wb)读取二进制而不是标准字符。我知道fread也将获得/ 0 Null字节,而不仅仅是一行。

  //while (fgets(buff,1023,fpinput) != NULL) //read in from file
  while (fread(buff, 1, 1023, fpinput) != 0) // read from file

我希望从文件读入缓冲区,将缓冲区放入共享内存中,然后让另一个进程从共享内存中读取并写入新文件。

当我使用fgets()时,它可以按预期与.txt文件一起使用,但是当使用fread时,它会将300〜个字符中的一行添加到缓冲区中,并换行。无法为我的生命找出原因。

1 个答案:

答案 0 :(得分:1)

fgets在遇到换行符时将停止。 fread没有。因此,fgets通常仅对文本文件有用,而fread既可以用于文本文件也可以用于二进制文件。

根据C11标准:

7.21.7.2 The fgets function

  

fgets函数从stream指向的流到s指向的数组中读取的字符数最多少于n指定的字符数。在换行符(保留)或文件结束之后,不会读取其他字符。在将最后一个字符读入数组后,立即写入空字符。

7.21.8.1 The fread function

  

fread函数从stream指向的流中读取ptr指向的数组中的多达nmemb元素,这些元素的大小由size指定。对于每个对象,都会对fgetc函数进行大小调用,并将结果按读取顺序存储在与对象完全重叠的无符号字符数组中。流的文件位置指示符(如果已定义)将提前成功读取的字符数。如果发生错误,则流的文件位置指示符的结果值不确定。如果读取了部分元素,则其值不确定。

此代码段可能会让您更清楚。它只是分块复制文件。

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char ** argv)
{
    if(argc != 3) {
        printf("Usage: ./a.out src dst\n");
        printf("Copies file src to dst\n");
        exit(EXIT_SUCCESS);
    }

    const size_t chunk_size = 1024;

    FILE *in, *out;
    if(! (in = fopen(argv[1], "rb"))) exit(EXIT_FAILURE);
    if(! (out = fopen(argv[2], "wb"))) exit(EXIT_FAILURE);

    char * buffer;
    if(! (buffer = malloc(chunk_size))) exit(EXIT_FAILURE);

    size_t bytes_read;

    do {
        // fread returns the number of successfully read elements
        bytes_read = fread(buffer, 1, chunk_size, in);

        /* Insert any modifications you may */
        /* want to do here                  */

        // write bytes_read bytes from buffer to output file
        if(fwrite(buffer, 1, bytes_read, out) != bytes_read) exit(EXIT_FAILURE);
   // When we read less than chunk_size we are either done or an error has 
   // occured. This error is not handled in this program. 
    } while(bytes_read == chunk_size); 


    free(buffer);
    fclose(out);
    fclose(in);
}

您在下面的评论中提到,您希望将其用于字节交换。好吧,您可以只使用以下代码段。只需将其插入上面代码中指示的位置即可。

for(int i=0; i < bytes_read - bytes_read%2; i+=2) {
    char tmp = buffer[i];
    buffer[i] = buffer[i+1];
    buffer[i+1] = tmp;
}