文件操作
1.C语言中的文件是什么?
所谓文件一般是指储存在外部介质上的数据集合,比如txt,bmp,jpg,exe,rmvb等
这些文件各有各的用途,我们通常将他们存放在磁盘或者可移动盘(U盘)等介质中
文件是一段数据的集合,这些数据可以是有规则的集合,也可以是无序的集合。操作系统也是以文件为单位对数据进行管理的。也就是说,要访问外部介质上的数据,必须先按照文件名查找,然后从该文件中读取数据。要想写入数据到外部介质,必须得建立一个文件,然后再写入。因此,眼前的文件只是数据的集合
2.文件三要素:文件路径,文件名,后缀
由于C语言中''一般是转义字符的起始标志,故在路径中需要用两个''表示路径中目录层次的间隔,也可以使用'/'作为路径的分隔符
例如:"F:\LoveHoneyYou_FILE\test.c"或者"F:/LoveHoneyYou_FILE/test.c",表示文件test.c保存在F盘LoveHoneyYou_FILE目录下
文件路径:可以显示指出其绝对路径,如上面的 " F:\ " 或者 " F:/"等
#define _CRT_SECURE_NO_WARNINGS #include#include int main() { FILE*fp = fopen("F:F:1LoveHoneyYou_FILELoveHoneyYou_FILE\LoveHoneyYou.txt", "w"); if (NULL == fp) { printf("打开失败!!n"); exit(1); } fclose(fp); fp = NULL; system("pause"); return 0; }
如果没有显示指出其路径,则为默认为当前路径,也就是相对路径
#define _CRT_SECURE_NO_WARNINGS #include#include int main() { FILE*fp = fopen("LoveHoneyYou.txt", "w"); if (NULL == fp) { printf("打开失败!!n"); exit(1); } fclose(fp); fp = NULL; system("pause"); return 0; }
数据的输入和输出几乎便随着每个C语言程序,所谓输入就是从"源端"获取数据,所谓输出可以理解为向"终端"写入数据。这里的源端可以是键盘,鼠标,硬盘,光盘,扫描仪等输入设备,终端可以是显示器,硬盘,打印机等输出设备。在C语言中,把这些输入和输出设备也看作"文件"
(才开始学总是会分不清方向----可简单的理解为,数据要从程序向外流出,就是输出;数据从别的地方需要流入程序就是输入。要有坚定的信仰,站在程序的角度出发)
3.预定义标准流
stdin 与标准输入流关联的FILE*类型表达式
stdout 与标准输出流关联的FILE*类型表达式
stderr 与标准错误输出流关联的FILE*类型表达式
4.流的概念和分类
标准C的I/O系统即标准I/O系统,把任意输入的源端或任意输出的终端,都抽象成了概念上的"标准IO设备"或称"标准逻辑设备"。程序绕过具体设备,直接与该"逻辑设备"进行交互,这样就为程序设计者提供了一个不依赖于任何具体IO设备的统一操作接口,通常把抽象出来的"标准逻辑设备"或"标准文件"称作"流"
把任意IO设备,转换成逻辑意义上的标准IO设备或者标准文件的过程,并不需要程序设计者感知和处理,是由标准IO系统自动完成的。在这个意义上,可认为任意输入的源端和输出的终端均对应一个"流"
1) 流按流行分为:输入流和输出流。从文件获取数据的流称为输入流,向文件输出数据称为输出流
2) 流按数据形式分为:文本流和二进制流。文本流是ASC||码字符序列,而二进制流是字节序列
3) 流是一种抽象概念,负责在数据的产生者和数据的使用者之间建立关系,并且管理数据的流动
5.二进制文件和文本文件的区别
根据数据的组织形式不同,可以把文件分为:文本文件和二进制文件
文本文件:把要存储的数据当成一系列字符组成,把每个字符的ASC||码值存入文件中。每个ASC||码值占一个字节,每个字节表示一个字符。所以文本文件也称字符文件,或ASC||文件,是字符序列文件。
写入:
#define _CRT_SECURE_NO_WARNINGS #include#include int main() { FILE*fp = fopen("Test.txt", "w"); if (fp == NULL) { exit(1); } int arr[] = { 12, 23, 34, 45, 56, 67, 78, 89, 90, 100 }; char buff[256] = { 0 }; int len = 0; for (int i = 0; i < 10; i++) { fprintf(fp, " %4d", arr[i]); //写入文件 fprintf(stdout, " %4d", arr[i]); //输出到屏幕 len += sprintf(buff+len, " %4d", arr[i]); //写入到buff缓冲区 } fclose(fp); fp = NULL; system("pause"); return 0; }
在内存中:
读取:
#include#include #define N 10 int main() { int arr[N] = { 0 }; FILE*fp = fopen("Test.txt", "r"); if (fp == NULL) { exit(1); } for (int i = 0; i < N; i++) { fscanf(fp,"%d", &arr[i]); } fclose(fp); fp = NULL; system("pause"); return 0; }
注:
在读取文件时,执行完此语句
会将fp和对应的磁盘文件关联起来
执行完这条语句
会一把将磁盘内对应文件的数据全部读入文件流缓冲区 ,我们打开内存观察
我们是通过循环一个一个的从缓冲区中取数据(字符),读取时会根据相应的格式将字符转换为需要的数据类型的数据
把结构体类型写以文本形式写入文件
#define _CRT_SECURE_NO_WARNINGS #include#include struct Student { char id[20]; char name[20]; char sex[8]; int age; }; int main() { struct Student s = { "2020032562", "LoveHoneyYou", "MAN", 20 }; FILE*fp = fopen("Student_Infor.txt", "w"); if (fp == NULL) { printf("打开失败!n"); exit(1); } fprintf(fp, "%sn", s.id); fprintf(fp, "%sn", s.name); fprintf(fp, "%sn", s.sex); fprintf(fp, "%dn", s.age); fclose(fp); fp = NULL; system("pause"); return 0; }
读取:
#define _CRT_SECURE_NO_WARNINGS #include#include struct Student { char id[20]; char name[20]; char sex[8]; int age; }; int main() { struct Student s = { 0 }; FILE*fp = fopen("Student_Infor.txt", "r"); if (fp == NULL) { exit(1); } fscanf(fp, "%s", s.id); fscanf(fp, "%s", s.name); fscanf(fp, "%s", s.sex); fscanf(fp, "%d", &s.id); fclose(fp); fp = NULL; system("pause"); return 0; }
注:
在读取时,要按照文件存放数据的顺序读取,不然就可能出现,s的姓名里却放的是其学号,诸如此类的问题
二进制文件:把数据对应的二进制形式存储到文件中,是字节序列文件
二进制文件写入函数:size_t fwrite (const void * ptr,size_t count ,FILE * stream)
函数参数:
ptr:这是指向要被写入元素的数组的指针
size:这是要被写入的每个元素的大小,以字节为单位
count:这是元素个数,每个元素的大小为size个字节
stream:这是指向FILE对象的指针,该FILE对象指定了一个输出流
返回写入成功元素的个数,若出现错误或到达文件末尾,则可能小于count
若返回的数值与count的数值不同,则写入错误将阻止函数完成。
#define _CRT_SECURE_NO_WARNINGS #include#include int main() { int arr[] = { 12, 23, 34, 45, 56, 67, 78, 89, 90, 100 }; int len = sizeof(arr) / sizeof(arr[0]); FILE*fp = fopen("Bin_File.txt", "wb"); if (fp == NULL) { printf("打开失败!n"); exit(1); } fwrite(arr, sizeof(arr[0]), len, fp); fclose(fp); fp = NULL; system("pause"); return 0; }
为什么在文本中显示是乱码呢?
在文本中显示时, 会将磁盘文件中的二进制数据,以字节为单位,显示成一个一个的字符
注:注意光标位置
文件流中内存显示:
结构体类型数据以二进制写入文件
#define _CRT_SECURE_NO_WARNINGS #include#include struct Student { char id[20]; char name[20]; char sex[8]; int age; }; int main() { struct Student s1 = { "2020032562", "LoveHoneyYou", "MAN", 20 }; FILE*fp = fopen("Bin_student.txt", "wb"); if (fp == NULL) { printf("打开失败!n"); exit(1); } fwrite(&s1, sizeof(struct Student), 1, fp); fclose(fp); fp = NULL; system("pause"); return 0; }
块数据读取函数:size_t fread (void * ptr ,size_t size ,size_t count,FILE * stream )
函数参数:
ptr:指向大小至少为(size*count) 字节的内存块,从流中读取的数据存储到ptr指向的内存
size:读取元素的大小,unsigned int
count:读取元素的个数
stream:是指向FILE对象的指针,该FILE对象制定了一个输入流
返回值:
返回成功读取的对象个数,若出现错误或到达文件末尾,则可能小于count
若size或count为零,则fread返回零且不进行其他动作
fread不区分文件尾和错误,因此调用者必须用feof和ferror才能判断发生了什么
#define _CRT_SECURE_NO_WARNINGS #include#include #define N 10 int main() { int arr[10] = { 0 }; FILE*fp = fopen("Bin_File.txt", "rb"); if (fp == NULL) { printf("打开失败!n"); exit(1); } fread(arr, sizeof(int), N, fp); fclose(fp); fp = NULL; system("pause"); return 0; }
二进制文件存储的结构体类型数据读取
#define _CRT_SECURE_NO_WARNINGS #include#include struct Student { char id[20]; char name[20]; char sex[8]; int age; }; int main() { struct Student tmp = { 0 }; FILE *fp = fopen("Bin_student.txt", "rb"); if (fp == NULL) { printf("打开失败!n"); exit(1); } fread(&tmp, sizeof(struct Student), 1, fp); fclose(fp); fp = NULL; system("pause"); return 0; }



