C语言教程(十七)文件管理

1. 简介

文件是数据的一种组织形式,以字节序列的形式存在于磁盘上。C语言提供了一个FILE对象,所有的文件操作都是围绕这个FILE对象来进行的,文件的基本信息就位于标准库文件<stdio.h>的FILE对象中。

开始对文件进行操作之前,首先定义一个FILE指针,FILE指针指向要操作的文件,用来保存文件信息。

FILE *f;//定义一个文件指针

2. 标准流

程序执行时会默认打开三个文件,可用于访问屏幕和键盘。

  • stdin:标准输入,键盘,编号为0;
  • stdout:标准输出,屏幕,编号为1;
  • stderr:标准错误,屏幕,编号为2。

3. 打开和关闭文件

3.1 fopen()函数

fopen()函数用于打开一个文件,这是文件读写操作的第一步。函数存在于库文件<stdio.h>中,原型如下。

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

fopen()函数接受两个参数,第一个参数是文件名称,第二个参数是访问模式,用于指定对文件的操作方式。该函数返回一个FILE指针,如果文件打开失败,则返回NULL(空指针)

FILE *f;
f = fopen("test.c", "r");//打开文件

上面的fopen()函数打开了一个test.c文件,模式为r,表示以读取模式打开文件。

fopen()函数的访问模式还有很多:

3.2 fclose()函数

fclose()函数用于关闭一个文件,这是文件读写操作的最后一步。函数存在于库文件<stdio.h>中,原型如下。

 int fclose(FILE *f);

fclose()函数接受一个文件指针参数,用于指定要关闭的文件。该函数返回一个int类型的整数值,如果关闭成功,返回0;如果关闭失败,则返回-1,即EOF。

注意:EOF是一个宏,一般读到文件末尾,就会返回这个值。

3.3 freopen()函数

freopen()函数也是打开一个文件,它用于重定向到指定的文件中,函数原型如下。

FILE* freopen(char* filename, char* mode, FILE* f);

freopen()函数比fopen()函数多了一个参数:FILE指针f,表示重定向的文件指针。

freopen("test.txt", "w", stdout);

上面的示例中,将文件test.txt关联到stdout,向stdout写入的内容,都会写到test.txt文件中。

4. 文件的读写

4.1 fgetc()与getc()

fgetc()函数和getc()函数的功能是一样的,用于从任意指定的文件中读取一个字符,区别在于getc()函数用宏实现的,fgetc()函数是用函数实现的,且都位于标准库头文件<stdio.h>中,函数的原型如下。

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

这两个函数都接受一个FILE指针,表示指向该文件。两者的返回值类型都是int,如果读取成功,返回对应的字符;如果读取失败则返回EOF值,即-1。

#include <stdio.h>

int main(void){

  FILE *f;//创建FILE指针
  f = fopen("test.txt","r");
  
  int c;
  while((c = getc(f)) != EOF){
      printf("%c\n",c);
  }
fclose(f);
}

4.2 fputc()与putc()

fputc()函数和putc()函数的功能是一样的,用于向任意指定的文件中写入一个字符,区别在于fgetc()函数用宏实现的,getc()函数是用宏实现的,且都位于标准库头文件<stdio.h>中,函数的原型如下。

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

这两个函数都接受两个参数,第一个参数是要写入的字符,第二个参数是FILE指针。两者返回值都是int类型,如果写入成功,则返回写入的字符;如果写入失败,则返回EOF值,即-1。

4.3 fprintf()与fscanf()

fprintf()函数用于向任意指定的文件中写入格式化字符串,定义在标准库头文件<stdio.h>中,函数原型如下。

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

该函数的第一个参数是FILE指针,第二个参数是指定格式,后面的参数是可变参数,和printf()函数类似。

fprintf(f, "%d\n", test);//向文件指针f写入指定格式的字符串

fprintf()函数可以实现printf()函数的功能,文件指定为stdout就可以了。

fprintf(stdout, "peiqiblog\n");

//等同于
printf("peiqiblog\n");

fscanf()函数用于从任意指定的文件中按照指定格式读取内容,定义在标准库头文件<stdio.h>中,函数原型如下。

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

该函数的第一个参数是FILE指针,第二个参数是指定格式,后面的参数是可变参数,和scanf()函数类似。返回值是int类型,如果读取成功,返回读取的变量数量,如果读取失败则返回EOF值,即-1。

fscanf(f, "%d", &i);

4.4 fgets()与fputs()

fgets()函数用于从任意指定的文件中读取指定长度的字符串,定义在标准库头文件<stdio.h>中,函数原型如下。

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

该函数接受三个参数,第一个参数是字符指针,用于存放读取的内容;第二个参数指定读取的字符串长度,第三个参数是FILE指针,指定要读取的文件。

fgets()函数读取到STRLEN-1字符后,或者读到了文件结尾或者遇到了换行符\n,就会停止读取,然后在已读取的内容末尾添加空字符\0表示结束。

fgets()函数返回值是char类型,指向该函数的第一个参数,否则读取失败,就会返回NULL。

#include <stdio.h>

int main(void){
   
   char c[256];
   FILE *f;
   f = fopen("test.txt","r");
    while (fgets(c, sizeof c, fp) != NULL){  //循环读取文件的每一行
    printf("%s",c);
   }
   fclose(f);
}

上面的示例使用fgets()函数读取文件的每一行,保存到字符指针c中并输出到屏幕上。

fputs()函数用于向任意指定的文件中写入字符串,定义在标准库头文件<stdio.h>中,函数原型如下。

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

该函数接受两个参数,第一个参数是要写入的字符串指针,第二个参数是FILE指针,指向要写入的文件。fputs()函数通常与fgets()函数配合使用。该函数返回一个int整数,写入失败则返回EOF值。

char *str = "peiqiblog";
fputs(str,stdout);

4.5 fread()与fwrite()

fread()函数是比较常用的,它用于从任意指定的文件中一次性读取较大的数据块,然后写入到数组中,常用于读取二进制数据。它定义在标准库文件<stdio.h>中,函数原型如下。

size_t fread(void *ptr,size_t size,size_t nmemb,FILE *stream)

该函数的功能是从指定的文件流stream读取数据存放到ptr指针指向的数组中。该函数有四个参数:

  • void *ptr:指向数组的指针,即数组的地址;
  • size_t size:读取的每个数组元素的大小,以字节为单位;
  • size_t nmemb:数组元素的个数,每个元素的大小为size个字节;
  • FILE *stream:指向文件的指针,这里指定了输入流。

该函数的返回值类型为size_t,如果读取成功,返回所读取的元素数量,也就是该函数的第三个参数nmemb,一般是与nmemb是相同的;如果读取失败,则返回值比nmemb小。

FILE *stream;
char str[];

stream = fopen("test.c","r");
while (fread(&str, sizeof(char), 1, stream) > 0){
   printf("%d\n", str);
}   
 fclose(stream);

上面的示例是调用fread()函数循环读取test.c文件中。

fwrite()函数和fread()函数表现基本类似,它用于向任意指定的文件中一次性写入较大的指定的数据块,常用于写入二进制数据。它定义在标准库文件<stdio.h>中,函数原型如下。

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

该函数的功能是将指针ptr指向的数组中的数据写入到指定的文件流stream中。该函数有四个参数:

  • void *ptr:指向数组的指针,这里指要被写入的数组的地址;
  • size_t size:被写入的每个数组元素的大小,以字节为单位;
  • size_t nmemb:数组元素的个数,每个元素的大小为size个字节;
  • FILE *stream:指向文件的指针,这里指定了输出流。

该函数的返回值类型为size_t,如果写入成功,返回所写入的元素总数量,也就是该函数的第三个参数nmemb,一般是与nmemb是相同的;如果写入失败,则返回值比nmemb小。

FILE *stream;
stream = fopen("test.c","w");//打开文件
char str[] = "peiqiblog";
fwrite(str,sizeof(str), 1,stream);//写入字符串
fclose(stream);

上面的示例是将字符串str的内容写入到test.c文件中。

4.6 fseek()

fseek()函数用于将任意指定的文件的定位设置为指定的位置,定义在标准库头文件<stdio.h>中,函数原型如下。

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

fseek()函数用于将指定的文件流stream的位置为指定的偏移offset,它接受三个参数:

  • FILE *stream:指向FILE文件的指针;
  • long int offset:相对 whence 的偏移量,以字节为单位;
  • int whence:表示开始添加偏移 offset 的位置,即offset的参照物。

whence参数一般指定为如下常量:

  • SEEK_SET:文件开始处;
  • SEEK_CUR:文件指针的当前位置;
  • SEEK_END:文件结尾处。

如果fseek()函数执行成功,则返回0,;如果操作失败,则返回一个负值。

FILE *stream;

stream = fopen("test.c","rw");
//定位到文件的开始处
fseek(stream,0L,SEEK_SET);

//定位到文件的第5个字节
fseek(stream,5L,SEEK_SET);

//定位到文件的当前位置后5个字节
fseek(stream,5L,SEEK_CUR);

//定位到文件的结尾
fseek(stream,0L,SEEK_END);

//定位到文件的结尾处前5个字节
fseek(stream,-5L,SEEK_END);

fclose(stream);

上面的示例中分别运用了三个基准常量值,可以定位到文件的各个位置,注意这里的偏移量是long类型,所以使用时要加上后缀L,转为long类型。

4.7 ftell()

ftell()函数用于获取指定文件内的当前位置,定义在标准库文件<stdio.h>中,函数原型如下。

long int ftell(FILE* stream);

该函数接受一个FILE指针作为参数,指向要操作的文件。返回值类型是long int。如果执行成功,则返回文件的开始到当前位置的字节数;如果执行失败,则返回-1L。ftell()函数通常与fseek()函数一起使用。

FILE *stream;

stream = fopen("test.c","rw");

fseek(stream,0L,SEEK_CUR);
long int size = ftell(stream);

fclose(stream);

上面的示例中,先使用fseek()函数定位到文件的当前位置,然后再获取从文件开始处到当前位置的字节数。

4.8 feof()

feof()函数用于判断文件内部(内部指针)是否到达了结尾,定义在标准库文件<stdio.h>中,函数原型如下。

int feof(FILE *fp);

该函数接受一个FILE指针为参数,表示要操作的文件。该函数返回一个int类型的值,如果内部指针已经指向了文件结尾,那么返回一个为零值;否则就返回0。

FILE *stream;

stream = fopen("test.c","rw");
int c;
while(1){

c = fgetc(stream);
if(foef(stream)){
    break;
  }
printf("%c\n",c);
}
fclose(stream);

上面是一个读取文件输出字符的示例,通过使用foef()函数判断是否到达结尾,到达结尾则退出循环。

4.9 ferror()

ferror()函数用于记录文件的错误状态,判断文件操作是否成功,定义在标准库文件<stdio.h>中,函数原型如下。

int ferror(FILE *stream);

该函数接受一个FILE指针,用于指向该文件。返回值是一个int类型,如果前面的文件操作成功,则返回0;如果操作中有错误,则返回一个非零值。

FILE *stream;

stream = fopen("test.c","rw");
int c;
while(1){

c = fgetc(stream);

if (ferror(stream)) {
  printf("读取文件test.txt中字符时发生错误\n");
}
}
fclose(stream);
觉得有帮助可以赞赏本文哦~万分感谢!
文章:C语言教程(十七)文件管理
作者:沛旗
链接:https://www.peiqiblog.com/article/3817/
版权声明::本博客站点所有文章除特别声明外,均采用 CC BY-NC-SA 4.0协议
转载请注明文章地址及作者哦~
暂无评论

发送评论(禁止发表一切违反法律法规的敏感言论) 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇