文件
磁盘上的文件是文件。
在程序设计中,从文件功能的角度来分类有两种文件:程序文件、数据文件。
程序文件
包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境后缀为.exe)。
数据文件
文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件。
文件的好处
编程的程序是在内存上运行的,程序的数据在内存中存储的,程序结束,数据丢失,掉电,数据丢失。如果想要保留内存上的数据,需要存储在本地硬盘的文件中,数据存储在硬盘文件,程序能够从文件读取数据,实现数据持久化。
文件名
文件名分为三个部分:文件路径+文件主干+文件后缀
c:\dice\test\hello.txt
文件路径:c:\dice\test
文件主干: hello
文件后缀:.txt
文件指针
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息,这些信息是保存在一个结构体变量中的。
文件指针的类型是FILE*类型的,是因为将该结构体重命名为FILE。
程序打开和关闭文件
fopen
fopen会返回一个文件指针,如果打开文件失败,会返回一个空指针。filename是文件名的地址,mode是访问文件的模式的地址。
文件名可以选择两种形式:绝对路径和相对路径
绝对路径:绝对路径是从盘开始到文件所在位置。
找到C:\Users\小猪猪\source\repos\test\test目录的hello.c
FILE* p = fopen("C:\\Users\\小猪猪\\source\\repos\\test\\test\\hello.txt", "r");
\\防止\和别的字符形成转义字符,这里\会和t形成转义字符,所以要使用\\。
相对路径:从该目录开始找到文件的路径。
当前路径为C:\Users\小猪猪\source\repos\test\test,是该项目的源文件.c所在路径
找到当去路径的hello.txt
FILE* p = fopen("hello.txt", "r");
找到C:\Users\小猪猪\source\repos\test读取hello.txt
FILE* p = fopen("..\\hello.txt", "r");
..是回到上一个目录
\\防止\和别的字符形成转义字符
第二个参数是模式有很多种。
w会重新创建文件。
fclose
如果关闭文件成功返回0。参数是流,因为是文件操作,这里的流都是文件指针。参数使用的是fopen返回的文件指针。对以及使用fclose的文件指针手动的置为NULL,防止错误使用。
文件读写函数
字符输入输出
fputc
fputc的功能是将字符写入文件中。返回值是写入字符的ASCII码值,如果写入失败返回EOF。第一个参数是字符的ASCII码值,第二个参数是写入的文件指针。
现在是写入数据,选择模式"w",选择写入模式,按照顺序写入数据。
fgetc
fgetc的功能是将文件内容以字符的形式读取到程序中。返回值是写入字符的ASCII码值,如果读取失败返回EOF。参数是读取的文件指针。
现在是读取数据,按顺序读取字符。
文本行输入输出
fputs
读取成功返回非负数,读取失败返回EOF。第一个参数是指向写入字符串的指针,第二个是文件指针。
文件里面数据换行是因为写入数据的时候加了换行'\n'。
fgets
fgets的功能是读取一行字符串,将这一行字符串存储起来。返回值是这一串字符首元素的地址,如果读取失败返回NULL空指针。第一个参数存储该字符串的地址,第二个参数是最多读取多少个字符,第三个参数是文件指针。
如果读取n个字符,实际上最多只会读取n-1个字符,第n个字符用来存储'\0'。
格式化输入输出
fprintf
fprintf的功能是完成格式化输出到文件。函数使用成功返回写入的字节数,使用失败返回负数。fprintf和printf使用上差不多一样,fprintf多第一个参数文件指针,使用的时候在最前面加一个文件指针即可。
fscanf
fscanf函数的功能是从文件读取格式化化的数据到程序中。函数返回值是读取了多少个数据。如果读取失败返回EOF。fscanf和scanf使用上差不多一样,fscanff多第一个参数文件指针,使用的时候在最前面加一个文件指针即可。
二进制输入输出
fwrite
fwrite函数的功能是以二进制的形式写入到文件中。返回值是实践写入的个数。第一个参数是指向数据的指针,第二个参数是一个元素字节大小,第三个参数是写入多少个元素,第四个参数是写入的文件指针。
有一些乱码是因为txt文本不认识二进制。
fread
fread函数的功能是在文件中读取数据存储到程序中。返回值是实践读取到的元素个数。第一个参数是存储的指针,第二个参数是读取的元素字节大小,第三个参数是读取的元素个数,第四个参数是文件指针。
随机读写
fseek
fseek的功能是将文件指针移动到指定的位置。第一个参数是文件指针,第二个参数是偏移量,第三个参数文件指针的位置:SEEK_CUR(当前文件指针所在的位置)、SEEK_END(文件的结尾)、SEEK_SET(文件的起始位置)。
如果文件里面是: 123456789
读取了两个字符后,当前文件指针指向3的位置。1是文件的开头。9的下一个位置是文件的结尾。
如果想要读取文件中的8,可以有三种方式。
fseek(p, 5, SEEK_CUR); // 从当前位置往后跳5个字符
fseek(p, 7, SEEK_SET); // 从起始的位置往后跳7个字符
fseek(p, -2, SEEK_END); // 从结尾的位置往前跳两个字符
调整完文件指针的位置后再读取。
如果已经向文件写了: 123456789
当前文件指针指向9的下一个位置。1是文件的开头。9的下一个位置是文件的结尾。
如果想要将文件中的8修改为0,可以有三种方式。
fseek(p, 5, SEEK_CUR); // 从当前位置往后跳5个字符
fseek(p, 7, SEEK_SET); // 从起始的位置往后跳7个字符
fseek(p, -2, SEEK_END); // 从结尾的位置往前跳两个字符
调整完文件指针的位置后再重新写。
ftell
ftell函数的功能是获得当前文件指针相对于起始位置的偏移量。
rewind
rewind函数的功能是将文件指针回到起始位置。
文本文件
根据数据的组织形式,数据文件分为文本文件和二进制文件。
数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件。
如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件。
10
文本: 00110001 00110000
文本文件是以ASCII码值存储的。两个字符,两个ASCII码值
二进制:00000000 00000000 00000000 00001010
二进制是一个整型大小,四个字节。
feof
feof函数的功能是判断文件结束的原因。不能使用feof的返回值来判断文件是否结束,而是在知道文件已经结束的情况下,判断是不是遇到文件结尾结束。
ferror
ferror的功能是判断文件是不是遇到错误结束。
文件缓冲区
文件缓冲区是用以暂时存放读写期间的文件数据而在内存区预留的一定空间。使用文件缓冲区可减少读取硬盘的次数。内存向磁盘输出数据,先送到内存中的缓冲区中,装满缓冲区再输出到磁盘上。磁盘向内存输出数据,先送到内存中的缓冲区,装满缓冲区再输出到内存中。
fclose函数关闭文件的时候,会刷新文件缓冲区。
fflush
刷新文件缓冲区。
使用fflush刷新缓冲区。查看数据是刷新缓冲区后才输出到磁盘。
#include <stdio.h>
#include <windows.h>
struct student
{
char name[10];
int age;
char sex[10];
};
int main()
{
FILE* p = fopen("hello.txt", "w");
if (p == NULL)
{
printf("打开文件失败\n");
return -1;
}
struct student s = { "dice", 0, "male" };
fprintf(p, "%s %d %s", s.name, s.age, s.sex);
printf("写入数据\n");
Sleep(10000);
fflush(p);
printf("刷新缓冲区,查看文件是否有数据\n");
Sleep(10000);
fclose(p);
p = NULL;
return 0;
}