C语言中文件的读写

2024 年 6 月 24 日 星期一(已编辑)
/ , ,
41
摘要
文件指针、fopen()、fclose()、EOF的介绍。
这篇文章上次修改于 2024 年 8 月 9 日 星期五,可能部分内容已经不适用,如有疑问可询问作者。

C语言中文件的读写

一.文件打开与关闭

文件指针

定义一个文件指针

FILE *fp;

fopen()

函数原型

FILE* fopen(char* filename, char* mode);

在通过 fopen 打开一个文件时,系统会先创建一个缓冲区,所有的读写操作其实就是针对缓冲区,而不是文件本身,如果打开失败会返回 NULL

fopen()的模式字符串有以下几种。

  • r:读模式,只用来读取数据。如果文件不存在,返回 NULL 指针。
  • w:写模式,只用来写入数据。如果文件存在,文件长度会被截为0,然后再写入;如果文件不存在,则创建该文件。
  • a:写模式,只用来在文件尾部追加数据。如果文件不存在,则创建该文件。
  • r+:读写模式。如果文件存在,指针指向文件开始处,可以在文件头部添加数据。如果文件不存在,返回 NULL 指针。
  • w+:读写模式。如果文件存在,文件长度会被截为0,然后再写入数据。这种模式实际上读不到数据,反而会擦掉数据。如果文件不存在,则创建该文件。
  • a+:读写模式。如果文件存在,指针指向文件结尾,可以在现有文件末尾添加内容。如果文件不存在,则创建该文件。

fopen()函数会为打开的文件创建一个缓冲区。读模式下,创建的是读缓存区;写模式下,创建的是写缓存区;读写模式下,会同时创建两个缓冲区。C 语言通过缓存区,以流的形式,向文件读写数据。

fclose()

函数原型

int fclose(FILE* stream);

自然,和前面动态创建内存一样,有始有终,打开了用完了还得记得关闭,它接受一个文件指针fp作为参数。如果成功关闭文件,fclose()函数返回整数0。

EOF

这是一个宏定义,它的值是 -1, 只需记住它不是在文件末尾。

二. 顺序读写

1.putc(),fputc()

函数原型

int fputc(int char, FILE *stream);
int putc(int char, FILE *stream);

这两个函数都是用于从文件写入一个字符,功能都一样,只不过 petc 是通过宏定义实现的,性能会更好。特别注意,这个返回的是整形,如果写入失败返回 `EOF(-1) .

写如一个小写字母a在文件开头

FILE * fp;
// 打开一个文件
fp = fopen(file_name,"r+");
// 判断是否打开成功
if(fp == NULL){
    printf("This file can't opne.\n");
}
if (putc(97,fp)==EOF){
    printf("写入失败");
}
fclose(fp);

2.getc(),fgetc()

函数原型

int fgetc(FILE *stream)
int getc(FILE *stream);

这两个函数都是用于从文件中获取一个字符,功能都一样,只不过 getc 是通过宏定义实现的,性能会更好。特别注意,这个返回的是整形,如果读取到末尾会返回 EOF(-1) .

循环读取整个文件

FILE * fp;
// 打开一个文件
fp = fopen(file_name,"r");
// 判断是否打开成功
if(fp == NULL){
    printf("This file can't opne.\n");
}
int c;
while((c=getc(fp))!=EOF){
    printf("%c",c);
}
fclose(fp);
特别注意的是,因为中文占两个字节,但是getc每次只会读取一个字节,所以文件中的中文会在显示的时候会出现乱码。

3.fgets()

作用: fgets()用于从文件读取指定长度的字符串。

char* fgets(char* str, int STRLEN, File* fp);

假设文件中的内容为如下:

// test.txt
abcdefg

代码如下:

FILE *p = fopen("test.txt","r");
char buff[7];
fgets(buff,sizeof(buff),p);
printf("%s",buff) // abcdef
fgets()读取 STRLEN - 1 个字符之后,或者遇到换行符与文件结尾,就会停止读取,然后在已经读取的内容末尾添加一个空字符\0,使之成为一个字符串。注意,fgets()会将换行符(\n)存储进字符串。

4.fputs()

作用: 向文件中写入一个字符串。

函数原型

int fputs(const char *str, FILE *stream);

参数

  • str:要写入的字符串(以 \0 结尾)。
  • stream:指向目标文件的指针。

返回值

  • 成功时返回一个非负值。
  • 失败时返回 EOF。

5.fprintf()

作用: 格式化文件写操作,将数据格式化输出到文件中去,并返回写入了多少个字符。

函数原型

int fprintf(FILE *stream, const char *format, ...);

fprintf()接受2个以上的参数。

  • stream:文件指针。
  • format:格式化字符串,和scanf()基本是一样的。
  • ...:需要被格式化的变量或者字符串等等。

通过fprintf我们可以向文件中格式化输入字符串。

FILE *p = fopen("data.txt","w");

fprintf(p,"Name: %s","aglorice");
// 等价于
fprintf(p,"Name: aglorice");
// 等价于
fputs("Name: aglorice",p);

特别注意fprintf()函数返回的是写入了多少个字符,例如:

int count = fprintf(p,"Name: %s","aglorice");
printf("count = %d",count); // 14

6.fscanf()

作用: 格式化文件读操作

函数原型

int fscanf(FILE *stream, const char *format, ...);

fscanf()接受3个以上的参数。

  • stream:文件指针。
  • format:格式化字符串,和scanf()基本是一样的。
  • ...:需要接受值得变量或者数组。

三.随机读写

1.fseek()

作用: 改变文件指针的位置,从而实现随机读写的操作。

每个文件指针都有一个内部指示器(内部指针),记录当前打开的文件的读写位置(file position).

函数原型

int fseek(FILE* stream, long int offset, int whence);

fseek()接受3个参数。

  • stream:文件指针。
  • offset:距离基准(第三个参数)的字节数。类型为 long int,可以为正值(向文件末尾移动)、负值(向文件开始处移动)或 0(保持不动)。
  • whence:位置基准,用来确定计算起点。它的值是以下三个宏(定义在stdio.h):SEEK_SET(文件开始处)、SEEK_CUR(内部指针的当前位置)、SEEK_END(文件末尾)

2.rewind()

作用 : 回到文件起始位置。

函数原型

void rewind(file* stream);

相当于使用fseek(p,0L,SEEK_SET);,只不过rewind没有返回值。

3.fread()

作用:fread()函数用于一次性从文件读取较大的数据块,主要用途是将文件内容读入一个数组,适合读取二进制数据。

函数原型

size_t fread(
  const void* ptr,
  size_t size,
  size_t nmemb,
  FILE* fp
);

它接受四个参数。

  • ptr:数组指针。
  • size:每个数组成员的大小,单位字节。
  • nmemb:数组成员的数量。
  • fp:要写入的文件指针。

4.fwrite()

作用:功能是向指定的文件中写入若干数据块, 如成功执行则返回实际写入的数据 块数目。

函数原型

size_t fwrite(
  const void* ptr,
  size_t size,
  size_t nmemb,
  FILE* fp
);

它接受四个参数。

  • ptr:数组指针。
  • size:每个数组成员的大小,单位字节。
  • nmemb:数组成员的数量。
  • fp:要写入的文件指针。

5.ftell()

作用: 返回当前文件指针指向的位置。

函数原型

long ftell(FILE *fp);

它接受一个参数。

  • fp:要写入的文件指针。

返回值

  • 返回文件指针指向的位置(字节为单位).
  • 出现错误返回-1L.
特别注意ftell()返回的是一个long int

借助fseek()我们可以读取文件的整个大小。

FILE *p = fopen("data.txt","r");
fseek(p,0L,SEEK_END);
printf("当前文件大小为 : %ld",ftell(p));

使用社交账号登录

  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...