说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家!
磁盘文件
指一组相关数据的有序集合,通常存储在外部介质(如磁盘)上,使用时才调入内存。
设备文件
在操作系统中把每一个与主机相连的输入、输出设备看作是一个文件,把它们的输入、输出等同于对磁盘文件的读和写。
计算机的存储在物理上是二进制的,所以物理上所有的磁盘文件本质上都是一样的:以字节为单位进行顺序存储。
从用户或者操作系统使用的角度(逻辑上)把文件分为:
ASCII
、UNICODE
等5678
的以ASCII
存储形式(ASCII码)为:(先将5678
转为ASCII
码值53、54、55、56
,再转为二进制)5678
的存储形式(二进制码)为:在C
语言中用一个指针变量指向一个文件,这个指针称为文件指针。
typedef struct
{short level; //缓冲区"满"或者"空"的程度 unsigned flags; //文件状态标志 char fd; //文件描述符unsigned char hold; //如无缓冲区不读取字符short bsize; //缓冲区的大小unsigned char *buffer;//数据缓冲区的位置 unsigned ar; //指针,当前的指向 unsigned istemp; //临时文件,指示器short token; //用于有效性的检查
}FILE;
FILE
是系统使用typedef
定义出来的有关文件信息的一种结构体类型,结构中含有文件名、文件状态和文件当前位置等信息。
声明FILE
结构体类型的信息包含在头文件"stdio.h"
中,一般设置一个指向FILE
类型变量的指针变量,然后通过它来引用这些FILE
类型变量。通过文件指针就可对它所指的文件进行各种操作。
C
语言中有三个特殊的文件指针由系统默认打开,用户无需定义即可直接使用:
scanf
、getchar
函数默认从此终端获得数据。printf
、puts
函数默认输出信息到此终端。perror
函数默认输出信息到此终端。任何文件使用之前必须打开:
#include
FILE * fopen(const char * filename, const char * mode);
filename:
需要打开的文件名,根据需要加上路径mode:
打开文件的模式设置NULL
第一个参数的几种形式:
FILE *fp_passwd = NULL;//相对路径:
//打开当前目录passdw文件:源文件(源程序)所在目录
FILE *fp_passwd = fopen("passwd.txt", "r");//打开当前目录(test)下passwd.txt文件
fp_passwd = fopen("./test/passwd.txt", "r");//打开当前目录上一级目录(相对当前目录)passwd.txt文件
fp_passwd = fopen("../passwd.txt", "r");//绝对路径:
//打开C盘test目录下一个叫passwd.txt文件
fp_passwd = fopen("c:/test/passwd.txt","r");
第二个参数的几种形式(打开文件的方式):
打开模式 | 含义 |
---|---|
r 或rb | 以只读方式打开一个文本文件(不创建文件,若文件不存在则报错) |
w 或wb | 以写方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件) |
a 或ab | 以追加方式打开文件,在末尾添加内容,若文件不存在则创建文件 |
r+ 或rb+ | 以可读、可写的方式打开文件(不创建新文件) |
w+ 或wb+ | 以可读、可写的方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件) |
a+ 或ab+ | 以添加方式打开文件,打开文件并在末尾更改文件,若文件不存在则创建文件 |
注意:
b
是二进制模式的意思,b
只是在Windows
有效,在Linux
用r
和rb
的结果是一样的Unix
和Linux
下所有的文本文件行都是\n
结尾,而Windows
所有的文本文件行都是\r\n
结尾Windows
平台下,以 “ 文本 ” 方式打开文件,不加b
:\r\n
” 转换成 “\n
”\n
” 转换成 “\r\n
” 写入Unix/Linux
平台下, “ 文本 ” 与 “ 二进制 ” 模式没有区别,“\r\n
” 作为两个字符原样输入输出示例1: 以只读方式打开一个文本文件(不创建文件,若文件不存在则报错)
#define _CRT_SECURE_NO_WARNINGS
#include int main()
{ //打开一个文件,成功返回FILE结构体地址,失败返回NULL// 返回的文件流指针标识了打开的那个文件FILE* fp = fopen("hello.txt", "r"); // 只读,不创建文件,若文件不存在则报错if (NULL == fp){perror("open error");return;}return 0;
}
输出结果
open error: No such file or directory
示例2: 以写方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件)
FILE* fp = fopen("hello.txt", "w"); // 以写方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件)
if (NULL == fp)
{perror("open error");return;
}
编辑"hello.txt
"文件,并填写数据后保存,如果再次执行代码,文件内容将被清空
任何文件在使用后应该关闭:
打开的文件会占用内存资源,如果总是打开不关闭,会消耗很多内存
一个进程同时打开的文件数是有限制的,超过最大同时打开文件数,再次调用fopen
打开文件会失败
如果没有明确的调用fclose
关闭打开的文件,那么程序在退出的时候,操作系统会统一关闭。
表头文件:#include
定义函数:int fclose(FILE * stream);
功能:关闭先前fopen()打开的文件。此动作让缓冲区的数据写入文件中,并释放系统所提供的文件资源。
参数:
stream:
文件指针
返回值:
成功:0
失败:-1
FILE* fp = fopen("hello.txt", "w"); // 以写方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件)
if (NULL == fp)
{perror("open error");return -1;
}
fclose(fp);
#include
int fputc(int ch, FILE * stream);
ch
转换为unsigned char
后写入stream
指定的文件中ch:
需要写入文件的字符stream:
文件指针-1
示例1:清空写入
FILE* fp = fopen("hello.txt", "w");
fputc('a', fp);
fclose(fp);
示例2:追加写入
FILE* fp = fopen("hello.txt", "a");
fputc('b', fp);
fclose(fp);
示例3:清空循环写入
FILE* fp = fopen("hello.txt", "w");
char buf[] = "this is a test for fputc";
int i = 0;
int n = strlen(buf);
for (i = 0; i < n; i++)
{//往文件fp写入字符buf[i]int ch = fputc(buf[i], fp);printf("ch = %c\n", ch);
}
fclose(fp);
#include
int fgetc(FILE * stream);
stream
指定的文件中读取一个字符stream:
文件指针-1
示例:读取文件中的内容
#define _CRT_SECURE_NO_WARNINGS
#include int main()
{FILE* fp = fopen("hello.txt", "r");char buf[128] = "";int i = 0;while ((buf[i++] = fgetc(fp)) != -1);printf("%s\n", buf);return 0;
}
在C
语言中,EOF
表示文件结束符(end of file
)。在while
循环中以EOF
作为文件结束标志,这种以EOF
作为文件结束标志的文件,必须是文本文件。在文本文件中,数据都是以字符的ASCII
代码值的形式存放。我们知道,ASCII
代码值的范围是0~127
,不可能出现-1
,因此可以用EOF
作为文件结束标志。
#define EOF (-1)
示例:使用EOF
作为结束符,存在的问题
// 写入-1
FILE* fp = fopen("hello.txt", "w");
if (NULL == fp)
{perror("open error");return -1;
}
char buf[10] = {97,-1,-2,98,99};
int i = 0;
while (buf[i] != 0)
{fputc(buf[i], fp);i++;
}
fclose(fp);
int main()
{ FILE* fp = fopen("hello.txt", "r");char buf[128] = "";int i = 0;while ((buf[i++] = fgetc(fp)) != EOF);printf("%s\n", buf);return 0;
}
当把数据以二进制形式存放到文件中时,就会有-1
值的出现,因此不能采用EOF
作为二进制文件的结束标志。为解决这一个问题,ANSI C
提供一个feof
函数,用来判断文件是否结束。feof函数既可用以判断二进制文件又可用以判断文本文件。
#include
int feof(FILE * stream);
stream:
文件指针0
值:已经到文件结尾0:
没有到文件结尾示例:使用feof
函数来判断文件是否结束
int main()
{ FILE* fp = fopen("hello.txt", "r");char buf[128] = "";int i = 0;do{buf[i++] = fgetc(fp);} while (!feof(fp));printf("%s\n", buf);return 0;
}
案例1:拷贝文本文件
#define _CRT_SECURE_NO_WARNINGS
#include void copyFile(char srcFileName[128], char dstFileName[128])
{// 打开src文件 创建dst文件FILE* fpread = fopen(srcFileName, "r");FILE* fpwrite = fopen(dstFileName, "w");if (NULL == fpread || NULL == fpwrite){perror("open error");return -1;}while (1){ int ch;// 读取src一个字符ch = fgetc(fpread);if (feof(fpread))break;// 写入到dst文件fputc(ch, fpwrite);}//关闭fclose(fpread);fclose(fpwrite);
}int main()
{ char srcFileName[128] = "hello.txt";char dstFileName[128] = "hello2.txt";copyFile(srcFileName, dstFileName);return 0;
}
案例2:拷贝图片文件
#define _CRT_SECURE_NO_WARNINGS
#include void copyFile(char srcFileName[128], char dstFileName[128])
{// 打开src文件 创建dst文件FILE* fpread = fopen(srcFileName, "rb"); FILE* fpwrite = fopen(dstFileName, "wb");if (NULL == fpread || NULL == fpwrite){perror("open error");return -1;}while (1){ int ch;// 读取src文件ch = fgetc(fpread);if (feof(fpread))break;// 写入到dst文件fputc(ch, fpwrite);}//关闭fclose(fpread);fclose(fpwrite);
}int main()
{ char srcFileName[128] = "csdn_cdtaogang_blog.png";char dstFileName[128] = "my_csdn_blog.png"; copyFile(srcFileName, dstFileName);return 0;
}
案例3:实现cat
命令,把文件内容输出到终端
#define _CRT_SECURE_NO_WARNINGS
#include int main()
{// 打开文件FILE *fpread = fopen("04拷贝案例.c", "r");if (NULL == fpread){perror("open error");return -1;}// 读取文件int ch;while (1){ch = fgetc(fpread);if (feof(fpread))break;fputc(ch, stdout); //输出到终端}fclose(fpread);return 0;
}
#include
int fputs(const char * str, FILE * stream);
str
所指定的字符串写入到stream
指定的文件中,字符串结束符 '\0'
不写入文件。str:
字符串stream:
文件指针0
-1
示例1:将一字符串写入到文件
#define _CRT_SECURE_NO_WARNINGS
#include int main()
{// 打开文件FILE *fpread = fopen("a.txt", "w");if (NULL == fpread){ perror("open error");return -1;}// 写入字符串char buf[] = "hellocdtaogang";fputs(buf, fpread);return 0;
}
示例2:按照行向文件写入数据,遇到\0
结束写入,遇到\n
就换行
int main()
{// 打开文件FILE *fpread = fopen("a.txt", "w");if (NULL == fpread){ perror("open error");return -1;}// 写入字符串,遇到\0就结束char buf[] = "hello\0cdtaogang";fputs(buf, fpread);return 0;
}
int main()
{// 打开文件FILE *fpread = fopen("a.txt", "w");if (NULL == fpread){ perror("open error");return -1;}// 写入字符串,遇到\0就结束,遇到\n就换行//char buf[] = "hello\0cdtaogang";char buf[] = "hello\ncdtaogang";fputs(buf, fpread);return 0;
}
#include
char * fgets(char * str, int size, FILE * stream);
stream
指定的文件内读入字符,保存到str
所指定的内存空间,直到出现换行字符、读到文件结尾或是已读了size - 1
个字符为止,最后会自动加上字符 '\0'
作为字符串结束。str:
字符串size:
指定最大读取字符串的长度(size - 1
)stream:
文件指针NULL
示例1:从文件中读取一字符串
#define _CRT_SECURE_NO_WARNINGS
#include int main()
{// 打开文件FILE* fpread = fopen("a.txt", "r");if (NULL == fpread){perror("open error");return -1;}char buf[1024] = "";// 读取文件fgets(buf, sizeof(buf), fpread);printf("%s", buf);fclose(fpread);return 0;
}
示例2:从文件中读取一字符串,遇到\n
就结束
示例3:使用fgets
和fputs
完成文本文件的拷贝(二进制文件图片读取无法使用,因为字符串二进制文件有很多0,fgets遇到0就读取结束了,同理fputs写入文件也是一样,所以它们只能操作文本文件)
int main()
{// 打开a文件 创建b文件FILE* fpread = fopen("a.txt", "r");FILE* fpwrite = fopen("b.txt", "w");if (NULL == fpread || NULL == fpwrite){perror("open error");return -1;}char buf[128] = "";char* p = NULL;while (1){// 读取a文件p = fgets(buf, sizeof(buf), fpread);if (NULL == p)break;// 写入到b文件fputs(buf, fpwrite);}//关闭fclose(fpread);fclose(fpwrite);return 0;
}
有个文件大小不确定,每行内容都是一个四则运算表达式,还没有算出结果,写一个程序,自动算出其结果后修改文件。
第一步:随机生成10个
四则运算表达式,并写入到文件中。
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#define CALC_NUM 10 // 要生成四则运算表达式的个数// 获取10个四则运算表达式并写入到文件中
void write_data()
{ // 生成并打开calc.txt文件FILE* fp = fopen("calc.txt", "w");if (NULL == fp){perror("open error");return -1;}// 设置随机种子srand(time(NULL));// 定义基本运算符数组char ysf[] = { '+', '-', '*', '/' };int a, b = 0;char c = 0;// 定义一个buf数组来保存四则运算表达式char buf[128] = "";for (int i = 0; i < CALC_NUM; i++){// 产生随机数1~100int a = rand() % 100 + 1;int b = rand() % 100 + 1;// 随机产生0~3的数int c = rand() % 4; // 0,1,2,3 对应运算符数组下标// 组包sprintf(buf, "%d%c%d=\n", a, ysf[c], b);printf(buf);// 写入到calc.txt文件中fputs(buf, fp);}// 关闭文件fclose(fp);
}int main()
{ // 调用write_data();return 0;
}
第二步:读取calc.txt
文件中的内容一行一行的读取,读取一次就进行解包计算结果,再将结果组包到表达式中
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#define CALC_NUM 10 // 要生成四则运算表达式的个数
#define FILE_PATH "calc.txt" // 文件路径// 封装打开文件方法
FILE* open_file(char* str)
{FILE* fp = fopen(FILE_PATH, str);if (NULL == fp){perror("open error");return -1;}return fp;
}// 封装关闭文件方法
void close_file(FILE* fp)
{fclose(fp);return;
}// 获取10个四则运算表达式并写入到文件中
void write_data()
{ // 生成并打开calc.txt文件FILE* fp = open_file("w");// 设置随机种子srand(time(NULL));// 定义基本运算符数组char ysf[] = { '+', '-', '*', '/' };int a, b = 0;char c = 0;// 定义一个buf数组来保存四则运算表达式char buf[128] = "";for (int i = 0; i < CALC_NUM; i++){// 产生随机数1~100int a = rand() % 100 + 1;int b = rand() % 100 + 1;// 随机产生0~3的数int c = rand() % 4; // 0,1,2,3 对应运算符数组下标// 组包sprintf(buf, "%d%c%d=\n", a, ysf[c], b);printf(buf);// 写入到calc.txt文件中fputs(buf, fp);}// 关闭文件close_file(fp);
}void read_data()
{ // 读取文件FILE* fp = open_file("r");int a, b = 0;char c = 0;char* p = NULL;char buf[128] = "";char new_buf[128] = "";int res = 0;while (1){p = fgets(buf, sizeof(buf), fp); //读一行的数据72*65=\nif (NULL == p){break;}// 拆包sscanf(buf, "%d%c%d", &a, &c, &b); // 72*65// switch判断运算符switch (c){case '+':res = a + b;break;case '-':res = a - b;break;case '*':res = a * b;break;case '/':res = a / b;break;}// 再组包,将计算结果组进去sprintf(new_buf, "%d%c%d=%d\n", a, c, b, res); // 72*65=4680\nprintf("%s", new_buf);}
}int main()
{ // 写入write_data();printf("\n");// 读取read_data();return 0;
}
第三步:如果直接从第二步去写入结果数据会导致原本的表达式数据被覆盖,比如calc.txt
文件13+15=28\n34-21=13\n...
在读取第一个\n
后写入会直接将\n
后面的数据覆盖掉,那么就读取不到后面的数据了,解决方法则是将每行组包数据保存到二维数组中即可
void read_data()
{ // 读取文件FILE* fp = open_file("r");int a, b = 0;char c = 0;char* p = NULL;char buf[128] = "";char new_buf[128] = "";int res = 0;// 定义二维数组保存每行组包结果数据char new_buff[10][128] = { 0 };int i= 0;while (1){p = fgets(buf, sizeof(buf), fp); //读一行的数据72*65=\nif (NULL == p){break;}// 拆包sscanf(buf, "%d%c%d", &a, &c, &b); // 72*65// switch判断运算符switch (c){case '+':res = a + b;break;case '-':res = a - b;break;case '*':res = a * b;break;case '/':res = a / b;break;}// 再组包,将计算结果组进去, //sprintf(new_buf[i], "%d%c%d=%d\n", a, c, b, res); // 72*65=4680\n//printf("%s", new_buf);sprintf(new_buff[i], "%d%c%d=%d\n", a, c, b, res); // 72*65=4680\ni++;}// 关闭文件close_file(fp);// 再次打开calc.txt文件,写入含结果的四则运算表达式fp = open_file("w");for (int j = 0; j < i; j++){fputs(new_buff[j], fp);}// 关闭文件close_file(fp);
}
也可以将新组包后的结果数据写入到指针数组中,只需要malloc申请空间即可保存组包数据。
char* new_buff[10] = { NULL };
int i= 0;
while (1)
{p = fgets(buf, sizeof(buf), fp); //读一行的数据72*65=\nif (NULL == p){break;}// 拆包sscanf(buf, "%d%c%d", &a, &c, &b); // 72*65// switch判断运算符switch (c){case '+':res = a + b;break;case '-':res = a - b;break;case '*':res = a * b;break;case '/':res = a / b;break;}// 再组包,将计算结果组进去, //sprintf(new_buf[i], "%d%c%d=%d\n", a, c, b, res); // 72*65=4680\n//printf("%s", new_buf);new_buff[i] = (char*)malloc(128);sprintf(new_buff[i], "%d%c%d=%d\n", a, c, b, res); // 72*65=4680\ni++;
}
#include
int fprintf(FILE * stream, const char * format, ...);
format
字符串来转换并格式化数据,然后将结果输出到stream
指定的文件中,指定出现字符串结束符 '\0'
为止。stream:
已经打开的文件format:
字符串格式,用法和printf()
一样-1
示例:使用fprintf
对比sprint
组包后fputs
写入
printf("%04d:%02d:%02d", year, month, day);
sprintf(buf, "%04d:%02d:%02d", year, month, day)
fprintf(fp, "%04d:%02d:%02d", year, month, day)
#define _CRT_SECURE_NO_WARNINGS
#include
#include int main()
{int year = 2022;int month = 12;int day = 2;char buf[128] = "";FILE* fp = NULL;fp = fopen("fprintf.txt", "w");if (!fp){perror("open error");return -1;}// 组包sprintf(buf, "%04d:%02d:%02d", year, month, day);// 写入文件fputs(buf, fp);return 0;
}
// 组包//sprintf(buf, "%04d:%02d:%02d", year, month, day);// 写入文件//fputs(buf, fp);//使用fprintf格式化写入文件fprintf(fp, "%04d:%02d:%02d", year, month, day);// 关闭文件fclose(fp);
#include
int fscanf(FILE * stream, const char * format, ...);
stream
指定的文件读取字符串,并根据参数format
字符串来转换并格式化数据。stream:
已经打开的文件format:
字符串格式,用法和scanf()
一样- 1
示例:使用fscanf
对文件数据进行拆包
scanf("%d:%d:%d", &year, &month, &day);
sscanf(buf, "%d:%d:%d", &year, &month, &day);
fscanf(fp, "%d:%d:%d", &year, &month, &day);
#define _CRT_SECURE_NO_WARNINGS
#include
#include int main()
{FILE* fp = NULL;fp = fopen("fprintf.txt", "r"); // 2022:12:02if (!fp){perror("open error");return -1;}int year = 0, month = 0, day = 0;// 使用fscanf进行数据拆包fscanf(fp, "%d:%d:%d", &year, &month, &day);printf("%d-%d-%d", year, month, day);// 关闭文件fclose(fp);return 0;
}
将10
个随机数写入到abc.txt
中,然后将abc.txt
文件中的随机数进行排序后写入
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#define CALC_NUM 10 // 要生成1~3位的整数个数
#define FILE_PATH "abc.txt" // 文件路径int main()
{// 设置随机种子,并写入数据FILE* fp = open_file("w");srand(time(NULL));for (int i = 0; i < CALC_NUM; i++){// 产生随机数1~300int num = rand() % 300 + 1;// 格式化后写入fprintf(fp, "%d\n", num);}// 关闭文件close_file(fp);// 读取文件中写入的随机数,并保存到数组中int num = 0;int nums[10] = { 0 };int n = sizeof(nums) / sizeof(nums[0]);fp = open_file("r");for (int i = 0; i < n; i++){// 格式化读取字符串fscanf(fp, "%d", &num);// 将随机数保存到数组中nums[i] = num;}close_file(fp);// 对nums数组元素进行排序for (int i = 0; i < n - 1; i++) //比较的轮数{ // 因为每次比较的次数都要减1,刚好i每次加1,所以每一轮比较的次数就是n-1-ifor (int j = 0; j < n - 1 - i; j++) // 每一轮比较的次数{if (nums[j] > nums[j + 1]) // 交换位置{int temp = nums[j];nums[j] = nums[j + 1];nums[j + 1] = temp;}}}// 再将排好序的nums数组写入到abc.txt文件fp = open_file("w");for (int i = 0; i < n; i++){ // 将nums每个元素进行组包fprintf(fp, "%d\n", nums[i]);}close_file(fp);return 0;
}
#include
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
ptr:
准备写入文件数据的地址size:
size_t
为 unsigned int
类型,此参数指定写入文件内容的块数据大小nmemb:
写入文件的块数,写入文件数据总大小为:size * nmemb
stream:
已经打开的文件指针nmemb
相等0
示例:
#define _CRT_SECURE_NO_WARNINGS
#include
#include typedef struct _std
{int age;char name[16];
}STD;int main()
{ int cont = 0;STD buf[3] = { {20, "cdtaogang"}, {21, "laoli"}, {22, "laozhao"} };FILE* fp = fopen("fwrite.txt", "w");// fwrite 第二个参数写1 ,是为了返回值刚好是写入文件的字节数,这也是个技巧cont = fwrite(buf, 1, sizeof(buf), fp);// cont = fwrite(buf, sizeof(buf), 1, fp);// 验证返回值是否等于字节数if (cont == sizeof(buf)){printf("cont == sizeof(buf) == %d", cont); // 60 (int:4 + char name[16]:16)*3}return 0;
}
#include
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
ptr:
存放读取出来数据的内存空间size:
size_t
为 unsigned int
类型,此参数指定读取文件内容的块数据大小nmemb:
读取文件的块数,读取文件数据总大小为:size * nmemb
stream:
已经打开的文件指针nmemb
小,但大于0
,说明读到文件的结尾。0
示例1:从结构体数组中,读取一个一个结构体大小
#pragma once
typedef struct _std
{int age;char name[16];
}STD;
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include "type.h"int main()
{ // 定义结构体数组STD buf[3];// 全部设置为0memset(buf, 0, sizeof(buf));FILE* fp = NULL;fp = fopen("fwrite.txt", "r"); if (!fp){perror("open error");return -1;}int cont = 0;// 从结构体数组中,读取一个一个结构体大小for (int i = 0; i < 3; i++){cont = fread(&buf[i], 1, sizeof(STD), fp);printf("cont=%d\n", cont);printf("%d %s\n", buf[i].age, buf[i].name);}return 0;
}
输出结果
cont=20
20 cdtaogang
cont=20
21 laoli
cont=20
22 laozhao
示例2:一次性读完整个结构体数组大小
int main()
{ // 定义结构体数组STD buf[3];// 全部设置为0memset(buf, 0, sizeof(buf));FILE* fp = NULL;fp = fopen("fwrite.txt", "r"); if (!fp){perror("open error");return -1;}int cont = 0;// 一次性读完整个结构体数组大小fread(buf, 1, sizeof(buf), fp);for (int i = 0; i < 3; i++){printf("%d %s\n", buf[i].age, buf[i].name);}return 0;
}
输出结果
20 cdtaogang
21 laoli
22 laozhao
实现二进制大文件的拷贝
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#define BUFFER_SIZE 1024 * 64int main()
{printf("Start Copy\n");// 拷贝的源地址char* src_file = "a.mp4";// 拷贝的目标地址char* dst_file = "b.mp4";// 以 可读 + 二进制 方式打开文件// r 表示可读打开方式// 打开方式后添加 b , 表示以二进制形式打开FILE* p_src = fopen(src_file, "rb");// 如果打开失败 , 直接返回if (p_src == NULL) {printf("src_file open failed");return 0;}// 以 可写 + 二进制 方式打开文件// w 表示可写打开方式// 打开方式后添加 b , 表示以二进制形式打开FILE* p_dst = fopen(dst_file, "wb");// 如果打开失败 , 直接返回if (NULL == p_dst) {printf("dst_file open failed");return 0;}// 为缓冲区内存申请堆内存char* buffer = malloc(BUFFER_SIZE);// 判定文件指针是否指向文件末尾// 如果指向末尾 , 说明该文件while (!feof(p_src)) {// 读取源文件数据到 buffer 缓冲区, 读取 buffer_size 个字节// 如果没有那么多字节 , 将读取的字节数返回int res = fread(buffer, 1, BUFFER_SIZE, p_src);// 将读取到缓冲区中的数据写出到目标文件中fwrite(buffer, 1, res, p_dst);}// 释放缓冲区内存free(buffer);// 关闭源文件fclose(p_src);// 关闭目标文件fclose(p_dst);printf("Copy Success");return 0;
}