文章目录

  • 一、文件
    • 1.1 文件类型指针
    • 1.2 文件的打开与关闭
      • 1.2.1 文件的打开
      • 1.2.2 文件的关闭
    • 1.3 文件的读写
      • 1.3.1 文本文件的读写
        • 1.3.1.1 写字符函数fputc和读字符函数fgetc
        • 1.3.1. 2 写字符串函数fputs和读字符串函数fgets
        • 1.3.1.3 格式化写函数fprintf和格式化读函数fscanf
      • 1.3.2 二进制文件的读写
        • 1.3.1 fread函数和fwrite函数
      • 1.3.3 文件的定位
        • 1.3.3.1 rewind()函数
        • 1.3.3.2 fseek()函数和随机读写
        • 1.3.3.3 ftell()函数
    • 1.4 文件的检测
      • 1.4.1 ferror()函数
      • 1.4.2 clearerr函数
    • 1.5 总结

一、文件

在程序运行时,常常需要将一些数据(运行的最终结果和中间数据)输出到磁盘上存放起来,以后需要时再从磁盘中输入到计算机内存。这就要用到磁盘文件。
C语言把文件看作是一个字符(字节)的序列,即一个一个字符(字节)的数据顺序组成。根据数据的组织形式,可分为ASCII文件和二进制文件。ASCII文件又称文本文件,它的每一个字节放一个ASCII代码,代表一个字符。二进制文件是把内存中的数据按其在内存中的存储形式原样输出到磁盘上存放。
        在过去使用的C版本(如UNIX系统下使用的C)有两种对文件的处理方法:一种叫“缓冲文件系统”,一种叫“非缓冲文件系统”。所谓缓冲文件系统是指系统自动地在内存中为每一个正在使用的文件名开辟一个缓冲区。从内存向磁盘输出数据必须先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘去。如果从磁盘向内存读入数据,则一次从磁盘文件将一批数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(给程序变量)。缓冲区的大小由各个具体的C版本确定,一般为512字节。


所谓“非缓冲文件系统”是指系统不自动开辟确定大小的缓冲区,而由程序为每个文件设定缓冲区。
在UNIX系统下,用缓冲文件系统来处理文本文件,用非缓冲文件系统处理二进制文件。用缓冲文件系统进行的输入输出又称为高级(或高层)磁盘输入输出(高层I/O),用非缓冲文件系统进行的输入输出又称为低级(低层)输入输出系统。ANSI C标准决定不采用非缓冲文件系统,而只采用缓冲文件系统。即既用缓冲文件系统处理文本文件,也用它来处理二进制文件。也就是将缓冲文件系统扩充为可以处理二进制文件。
在C语言中,没有输入输出语句,对文件的读写都是用库函数来实现的。ANSI规定了标准输入输出函数,用它们对文件进行读写。

1.1 文件类型指针

缓冲文件系统中,关键的概念是“文件指针”。每个被使用的文件都在内存中开辟一个区,用来存放文件的有关信息(如文件的名字、文件状态及文件当前位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是由系统定义的,取名为FILE。

1.2 文件的打开与关闭

1.2.1 文件的打开

#include <malloc.h>
#include <stdio.h>
// 主函数
int main(int argc, char *argv[]) // *argv[]:指针数组
{FILE *fp; // 文件指针fp = fopen("input.txt","r"); // 打开文件read/write fucntions // 读或者写函数fclose(fp); // 关闭文件指针return 0;
}

说明

(1)用“r”方式打开的文件只能用于向计算机输入而不能用作向该文件输出数据,而且该文件应该已经存在,不能用“r”方式打开一个并不存在的文件(即输入文件),否则出错。
(2)用“w”方式打开的文件只能用于向该文件写数据(即输出文件),而不能用来向计算机输入。如果原来不存在该文件,则在打开时新建立一个以指定的名字命名的文件。如果原来已存在一个以该文件名命名的文件,则在打开时将该文件删去,然后重新建立一个新文件。
(3)如果希望向文件末尾添加新的数据(不希望删除原有数据),则应该用“a”方式打开。但此时该文件必须已存在,否则将得到出错信息。打开时,位置指针移到文件末尾。
(4)用“r+”、“w+”、 “a+”方式打开的文件既可以用来输入数据,也可以用来输出数据。用“r+”方式时该文件应该已经存在,以便能向计算机输入数据。用“w+”方式则新建立一个文件,先向此文件写数据,然后可以读此文件中的数据。用“a+”方式打开的文件,原来的文件不被删去,位置指针移到文件末尾,可以添加,也可以读。
(5)如果不能实现“打开”的任务,fopen函数将会带回一个出错信息。出错的原因可能是用“r”方式打开一个并不存在的文件;磁盘出故障;磁盘已满无法建立新文件等。此时fopen函数将带回一个空指针值NULL。
(6)在向计算机输入文本文件时,将回车换行符转换为一个换行符,在输出时把换行符转换成为回车和换行两个字符。在用二进制文件时,不进行这种转换,在内存中的数据形式与输出到外部文件中的数据形式完全一致,一一对应。
(7)在程序开始运行时,系统自动打开3个标准文件:标准输入、标准输出、标准出错输出。这3个文件都与终端相联系。因此以前所用到的从终端输入或输出都不需要打开终端文件。系统自动定义了3个文件指针stdin、stdout和stderr,分别指向终端输入、终端输出和标准出错输出(也从终端输出)。如果程序中指定要从stdin所指的文件输入数据,就是指从终端键盘输入数据。

1.2.2 文件的关闭

在使用完一个文件后应该关闭它,以防止它再被误用。“关闭”就是使文件指针变量不指向该文件,也就是文件指针变量与文件“脱钩”,以后不能再通过该指针对原来与其相联系的文件进行读写操作。除非再次打开,使该指针变量重新指向该文件。

1.3 文件的读写

1.3.1 文本文件的读写

1.3.1.1 写字符函数fputc和读字符函数fgetc

1、从键盘输入一些字符,逐个把它们送到磁盘上去,直到输入一个“#”为止

#include <stdio.h>
#include <stdlib.h>// 主函数
int main(int argc, char *argv[]) // *argv[]:指针数组
{FILE *fp;fp = fopen("input.txt", "r");if (fp == NULL){exit(1);}char c;c = fgetc(fp);while (c != EOF){putchar(c);c = fgetc(fp);}return 0;
}
#include <stdio.h>
#include <stdlib.h>// 主函数
int main(int argc, char *argv[]) // *argv[]:指针数组
{FILE *fp;char filename[10]; //文件名printf("input file name: ");scanf("%s", &filename);if ((fp = fopen(filename, "w")) == NULL){exit(1);}fflush(stdin); // 将缓冲区内的数据写回参数stream指定的文件中printf("input character\n");char c;c = getchar(); // 输入字符while (c != '#') // 判别{fputc(c, fp);c = getchar();}return 0;
}

2、 将一个磁盘文件中的信息复制到另一个磁盘文件中

#include <stdio.h>
#include <stdlib.h>// 主函数
int main(int argc, char *argv[]) // *argv[]:指针数组
{FILE *in, *out;char infile[10]; //文件名char outfile[10];printf("enter the infile name:\n");scanf("%s", infile);printf("enter the outfile name:\n");scanf("%s", outfile);if ((in = fopen("input.txt", "rb")) == NULL)exit(0);if ((out = fopen("out.txt", "wb")) == NULL)exit(0);char c;c = fgetc(in);while (!feof(in)) // 判断文件是否结果{                // 判断文件不为空fputc(c, out); // 写入到out.txt文件中c = fgetc(in); // 循环读取下一个字符}fclose(in);fclose(out);return 0;
}

1.3.1. 2 写字符串函数fputs和读字符串函数fgets

1、将学生数据,由键盘输入并存储到磁盘文件中

#include <stdio.h>
#include <stdlib.h>// 主函数
int main(int argc, char *argv[]) // *argv[]:指针数组
{FILE *fp;char student[50]; // 创建字符数组-存储输入的字符串printf("input filename:");scanf("%s", student);if ((fp = fopen("input.txt", "w")) == NULL){exit(1);}for (int i = 0; i < 3; i++){gets(student); // 获取输入的字符串fputs(student, fp);// 存储到文件fpfputs("\n", fp);}fclose(fp);return 0;
}

2、从上例文件中读取学生数据,并显示在屏幕上

#include <stdio.h>
#include <stdlib.h>// 主函数
int main(int argc, char *argv[]) // *argv[]:指针数组
{FILE *fp;if ((fp = fopen("input.txt", "r")) == NULL)exit(0);char string[80];while (fgets(string, 80, fp) != NULL){printf("%s", string);}fclose(fp);return 0;
}

1.3.1.3 格式化写函数fprintf和格式化读函数fscanf

1、将学生数据,由键盘输入并存储到磁盘文件中

#include <stdio.h>
#include <stdlib.h>// 主函数
int main(int argc, char *argv[]) // *argv[]:指针数组
{FILE *fp;if ((fp = fopen("input.txt", "w")) == NULL)exit(0);long num;char name[10];int age;for (int i = 0; i < 5; i++) {printf("第%d个学生:\n", i + 1);printf("学号:\n");scanf("%ld", &num);printf("姓名:\n");scanf("%s", &name);printf("年龄:\n");scanf("%d", &age);fprintf(fp, "学号:%ld 姓名:%9s 年龄:%d\n", num, name, age);}fclose(fp);return 0;
}

2、从上例文件中读取学生数据,并显示在屏幕上

#include <stdio.h>
#include <stdlib.h>// 主函数
int main(int argc, char *argv[]) {FILE *fp;if ((fp = fopen("student.txt", "r")) == NULL)exit(0);long num;char name[10];int age;while (!feof(fp)) {// fprintf(fp, "学号:%ld 姓名:%9s 年龄:%d\n", num, name, age);fscanf(fp, "学号:%ld 姓名:%9s 年龄:%d\n", &num, name, &age);printf("%ld %s %d\n", num, name, age);}fclose(fp);return 0;
}

1.3.2 二进制文件的读写

1.3.1 fread函数和fwrite函数

从键盘输入4个学生数据,然后把它们转存到磁盘文件上去,然后再从磁盘文件中一次性读入内存并显示出来

#include <stdio.h>
#include <stdlib.h>struct student
{long num;char name[10];int age;
} s[4];// 主函数
int main(int argc, char *argv[])
{FILE *fp;if ((fp = fopen("student.dat", "w")) == NULL)exit(0);for (int i = 0; i < 4; i++){printf("第%d个学生:\n", i + 1);printf("学号:\n");scanf("%ld", &s[i].num);printf("姓名:\n");scanf("%s", s[i].name);printf("年龄:\n");scanf("%d", &s[i].age);}fwrite(s, sizeof(struct student), 4, fp);rewind(fp);// for (int i = 0; i < 4; i++)// {//   fread(&s, sizeof(struct student), 1, fp);//   printf("%ld %s %d\n", s->num, s->name, s->age);// }fread(s, sizeof(struct student), 4, fp);for (int i = 0; i < 4; i++){printf("%ld %s %d\n", s[i].num, s[i].name, s[i].age);}fclose(fp);return 0;
}

1.3.3 文件的定位

文件中有一个位置指针,指向当前读写的位置。如果顺序读写一个文件,每次读写一个字符,则读写完一个字符后,该位置指针自动移动指向下一个字符位置。如果想改变这样的规律,强制使位置指针指向其他指定的位置,可以用有关函数。

1.3.3.1 rewind()函数

rewind函数的作用是使位置指针重新返回文件的开头,此函数没有返回值。
有一个磁盘文件,第一次将它的内容显示在屏幕上,第二次把它复制到另一文件上

/** @Author: jjk* @Date: 2019-03-31 10:02:20* @Last Modified by: jjk* @Last Modified time: 2019-04-02 13:15:13*/#include <stdio.h>
#include <stdlib.h>struct student
{long num;char name[10];int age;
} s[4];// 主函数
int main(int argc, char *argv[])
{FILE *fp;if ((fp = fopen("input.txt", "r")) == NULL)exit(0);char c;c = fgetc(fp);while (!feof(fp)){printf("%c", c);c = fgetc(fp);}FILE *fp2;if ((fp2 = fopen("student2.txt", "w")) == NULL)exit(0);rewind(fp); // 重置文件指针c = fgetc(fp);while (!feof(fp)){fputc(c, fp2);c = fgetc(fp);}fclose(fp);fclose(fp2);fclose(fp);return 0;
}

1.3.3.2 fseek()函数和随机读写

对流式文件可以进行顺序读写,也可以进行随机读写,关键在于控制文件的位置指针。如果位置指针是按字节位置顺序移动的,就是顺序读写;如果能将位置指针按需要移动到任意位置,就可以实现随机读写。所谓随机读写,是指读写完上一个字符(字节)后,并不一定要读写其后的字符(字节),而可以读写文件中任意位置上所需要的字符(字节)。

 用fseek函数可以实现改变文件的位置指针。在磁盘文件上存有10个学生的数据。要求将第1、3、5、7、9个学生数据输入计算机,并在屏幕上显示出来
/** @Author: jjk* @Date: 2019-03-31 10:02:20* @Last Modified by: jjk* @Last Modified time: 2019-04-02 13:15:13*/#include <stdio.h>
#include <stdlib.h>struct student
{long num;char name[10];int age;
} s[10];// 主函数
int main(int argc, char *argv[])
{FILE *fp;if ((fp = fopen("student.dat", "w+")) == NULL)exit(0);for (int i = 0; i < 10; i++){printf("第%d个学生:\n", i + 1);printf("学号:\n");scanf("%ld", &s[i].num);printf("姓名:\n");scanf("%s", s[i].name);printf("年龄:\n");scanf("%d", &s[i].age);}fwrite(s, sizeof(struct student), 10, fp);struct student stu;for (int i = 1; i <= 9; i = i + 2){fseek(fp, (i - 1) * sizeof(struct student), SEEK_SET);fread(&stu, sizeof(struct student), 1, fp);printf("%ld %s %d\n", stu.num, stu.name, stu.age);}fclose(fp);return 0;
}

1.3.3.3 ftell()函数

ftell函数的作用是得到流失文件中的当前位置,用相对于文件开头的位移量来表示。由于文件中的位置指针经常移动,往往不容易知道其当前位置。用ftell函数可以得到当前位置。

#include <stdio.h>
#include <stdlib.h>// 主函数
int main(int argc, char *argv[])
{FILE *stream;long position;char list[100];if ((stream = fopen("7-4-1.avi", "rb")) != NULL) // 二进制文件{// Move the pointer by reading data:fread(list, sizeof(char), 100, stream);// Get position after read:position = ftell(stream); // 获取当前指针位置printf("Position after trying to read 100 bytes: %ld\n", position);fclose(stream);}fclose(stream);return 0;
}

1.4 文件的检测

1.4.1 ferror()函数

1.4.2 clearerr函数

#include <stdio.h>
#include <stdlib.h>// 主函数
int main(int argc, char *argv[]) {int count, total = 0;char buffer[100];FILE *stream;long position;char list[100];if ((stream = fopen("input.txt", "r")) == NULL)exit(1);int c;putc('c', stdin); //标准写入if (ferror(stdin)) {perror("Write error");//clearerr(stdin); // 清除这个错误:标准的输入文件处于正常状态}/* See if read causes an error. */printf("Will input cause an error? ");c = getc(stdin);if (ferror(stdin)) {perror("Read error");clearerr(stdin);}fclose(stream);return 0;
}

1.5 总结

【C语言】文件(FILE)相关推荐

  1. C语言文件缓冲区作用,C语言 文件操作4--文件结构体FILE的理解以及缓冲区再讲...

    //文件结构体FILE的理解以及缓冲区再讲 #include #include //要点:文件结构 //struct _iobuf { // char *_ptr; ------当前缓冲区内容指针 / ...

  2. go语言中的文件file操作

    一.File文件操作 首先,file类是在os包中的,封装了底层的文件描述符和相关信息,同时封装了Read和Write的实现. 1.FileInfo接口 FileInfo接口中定义了File信息相关的 ...

  3. C语言使用FILE指针文件操作

    C语言使用FILE指针文件操作 文件的基本概念 所谓"文件"是指一组相关数据的有序集合.这个数据集有一个名称,叫做文件名.实际上我们已经多次使用了文件,例如源程序文件.目标文件.可 ...

  4. linux c文件操作,C语言文件操作(FILE)与常用文件操作函数

    文件 1.文件基本概念 C程序把文件分为ASCII文件和二进制文件,ASCII文件又称文本文件,二进制文件和文本文件(也称ASCII码文件)二进制文件中,数值型数据是以二进制形式存储的, 而在文本文件 ...

  5. 测试必备技能之C语言文件函数(超级全能篇)——FILE函数

    之前出过的文件FILE函数的小白篇,现在出一个全面一些的 以下讲解直接分为函数原型+函数作用+测试用例 让大家真真正正的理解和感受这几个FILE函数的作用 二话不说,开冲! 额-先来个小表格: 在这里 ...

  6. c语言file的作用是什么意思,C语言文件操作之文件打开方式

    贴上一段: fopen函数用来打开一个文件,其调用的一般形式为: 文件指针名=fopen(文件名,打开文件方式); 其中, "文件指针名"必须是被说明为FILE类型的指针变量: & ...

  7. c语言生成文件可以删,C语言-文件操作下

    文件操作下 各种printf对比记忆 printf--sprintf--fprintf 都是变参函数:参数形参中有"...",最后一个固参通常是格式描述串(包含格式匹配符),函数的 ...

  8. c语言生成随机坐标,C语言 文件的随机读写详解及示例代码

    前面介绍的文件读写函数都是顺序读写,即读写文件只能从头开始,依次读写各个数据.但在实际开发中经常需要读写文件的中间部分,要解决这个问题,就得先移动文件内部的位置指针,再进行读写.这种读写方式称为随机读 ...

  9. c语言文件可用代码存放,C语言 文件(示例代码)

    小白一个,看到有错误,希望指出,万分感谢 /**************************************************************** C语言文件概述: 一般文件 ...

  10. C语言文件操作解析(二)【转载】

    http://www.cnblogs.com/dolphin0520/archive/2011/10/05/2199598.html C语言文件操作解析(二) C语言中对文件进行操作必须首先打开文件, ...

最新文章

  1. 在Jira停售后,你决定赌Atlassian Data Center?
  2. 【转载】CentsOS系统inotify实时监控服务器文件(夹)定制事件处理程序
  3. 李开复:AI行业正在回归商业本质,技术公司要有服务心态落地为王 | MEET2020
  4. Medoo入门:安装和配置-Medoo使用指南
  5. opencv+python机读卡识别(四)百度API进行数字识别
  6. win7完整卸载oracle11,win7安装与卸载oracle11g(32)
  7. 【图论】Tarjan 缩点
  8. 如何查看AWS实例上使用的key value pair名称
  9. python编程入门单例_python实现单例模式怎么写啊?
  10. 第二篇 Python图片处理模块PIL(pillow)
  11. Kafka将逐步弃用对zookeeper的依赖
  12. C#通过正则表达式判断字符是否为数字
  13. Vue学习笔记(利用网易云API实现音乐播放器 实例)
  14. wps页眉偶数页不同怎么设置_请问在wps文档中如何设置奇偶页不同的页眉
  15. android 菜鸟面单打印_Android开发的菜鸟小记
  16. 基于NodeJS实现企业微信机器人推送
  17. 【小月电子】ALTERA FPGA开发板系统学习教程-LESSON5数码管动态显示
  18. 人大金仓(Kingbase)数据库配置注意事项
  19. python dot_graphviz,dot,及dot图可视化
  20. 【行为分析】(一)宏观简介

热门文章

  1. 运动蓝牙耳机哪个品牌好、2023年最出色运动蓝牙耳机推荐
  2. antd权限管理_ANTDPRO权限如何设置?
  3. 性能魔方mmTrix:应用优质体验背后的护花使者
  4. JQ循环获取input的值 $(...)[i].val is not a function
  5. 惊!阿里双11数据中心来了一位顶级“刺客”?
  6. 清华大学计算机系 贾珈老师,清华大学计算机科学与技术系60周年系庆代际创新论坛...
  7. 彻底告别加解密模块代码拷贝-JCE核心Cipher详解
  8. https双向认证试验
  9. [云炬创业基础笔记]识别创业机会的方法之二—趋势观察法
  10. 2009台北国际电脑展十大新品