C语言 文件操作
文件概述
一、磁盘文件和设备文件
1、磁盘文件
指一组相关数据的有序集合,通常存储在外部介质(如磁盘)上,使用时才调入内存。
2、设备文件
在操作系统中把每一个与主机相连的输入、输出设备看作是一个文件,把它们的输入、输出等同于对磁盘文件的读和写。
二、磁盘文件的分类
计算机的存储在物理上是二进制的,所以物理上所有的磁盘文件本质上都是一样的:以字节为单位进行顺序存储。
从用户或者操作系统使用的角度(逻辑上)把文件分为:
- 文本文件:基于字符编码的文件
- 二进制文件:基于值编码的文件
三、文本文件和二进制文件
1、文本文件
- 基于字符编码,常见编码有ASCII、UNICODE等
- 一般可以使用文本编辑器直接打开
数5678的以ASCII存储形式(ASCII码)为:
00110101 00110110 00110111 00111000
2、二进制文件
- 基于值编码,自己根据具体应用,指定某个值是什么意思
- 把内存中的数据按其在内存中的存储形式原样输出到磁盘上
数5678的存储形式(二进制码)为:
00010110 00101110
文件打开和关闭
一、文件指针
在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语言中有三个特殊的文件指针由系统默认打开,用户无需定义即可直接使用:
- stdin: 标准输入,默认为当前终端(键盘),我们使用的scanf、getchar函数默认从此终端获得数据。
- stdout:标准输出,默认为当前终端(屏幕),我们使用的printf、puts函数默认输出信息到此终端。
- stderr:标准出错,默认为当前终端(屏幕),我们使用的perror函数默认输出信息到此终端。
二、文件打开
1、说明
任何文件使用之前必须打开:
#include <stdio.h> FILE * fopen(const char * filename, const char * mode);
功能:打开文件
参数:
- filename:需要打开的文件名,根据需要加上路径
- mode:打开文件的模式设置
返回值:
- 成功:文件指针
- 失败:NULL
2、第一个参数的几种形式
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");
3、第二个参数的几种形式(打开文件的方式)
注意事项:
- b是二进制模式的意思,b只是在Windows有效,在Linux用r和rb的结果是一样的
- Unix和Linux下所有的文本文件行都是\n结尾,而Windows所有的文本文件行都是\r\n结尾
- 在Windows平台下,以“文本”方式打开文件,不加b:
- 当读取文件的时候,系统会将所有的 "\r\n" 转换成 "\n"
- 当写入文件的时候,系统会将 "\n" 转换成 "\r\n" 写入
- 以"二进制"方式打开文件,则读\写都不会进行这样的转换
- 在Unix/Linux平台下,“文本”与“二进制”模式没有区别,"\r\n" 作为两个字符原样输入输出
打开模式 |
含义 |
r或rb |
以只读方式打开一个文本文件(不创建文件,若文件不存在则报错) |
w或wb |
以写方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件) |
a或ab |
以追加方式打开文件,在末尾添加内容,若文件不存在则创建文件 |
r+或rb+ |
以可读、可写的方式打开文件(不创建新文件) |
r+或rb+ |
以可读、可写的方式打开文件(不创建新文件) |
w+或wb+ |
以可读、可写的方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件) |
a+或ab+ |
以添加方式打开文件,打开文件并在末尾更改文件,若文件不存在则创建文件 |
4、案例
#include <stdio.h> int main(void) { FILE *fp = NULL; // "\\"这样的路径形式,只能在windows使用 // "/"这样的路径形式,windows和linux平台下都可用,建议使用这种 // 路径可以是相对路径,也可是绝对路径 fp = fopen("../test", "w"); //fp = fopen("..\\test", "w"); if (fp == NULL) //返回空,说明打开失败 { //perror()是标准出错打印函数,能打印调用库函数出错原因 perror("open"); return -1; } return 0; }
三、文件关闭
1、说明
任何文件在使用后应该关闭:
- 打开的文件会占用内存资源,如果总是打开不关闭,会消耗很多内存
- 一个进程同时打开的文件数是有限制的,超过最大同时打开文件数,再次调用fopen打开文件会失败
- 如果没有明确的调用fclose关闭打开的文件,那么程序在退出的时候,操作系统会统一关闭。
#include <stdio.h>
int fclose(FILE * stream);
功能:关闭先前fopen()打开的文件。此动作让缓冲区的数据写入文件中,并释放系统所提供的文件资源。
参数:
- stream:文件指针
返回值:
- 成功:0
- 失败:-1
2、案例
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <time.h> int main(void) { // 定义文件指针 FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r"); // 判断文件是否打开成功 // 1、找不到文件 // 2、文件权限(读、写、执行) // 3、程序打开文件超出上限 65535 if (fp == NULL) { printf("打开文件失败\n"); return -1; } printf("文件打开成功:%p\n",fp); // 关闭文件指针 fclose(fp); return 0; }
文件字符读写
一、写文件
1、说明
#include <stdio.h> int fputc(int ch, FILE * stream);
功能:将ch转换为unsigned char后写入stream指定的文件中
参数:
- ch:需要写入文件的字符
- stream:文件指针
返回值:
- 成功:成功写入文件的字符
- 失败:返回-1
2、案例
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <time.h> int main(void) { // 以写的方式打开文件、如果文件不存在则创建一个新文件、如果文件存在则清空内容 FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "w"); if (!fp) { printf("打开文件失败\n"); return -1; } // 创建字符 // char ch = \'a\'; // 字符写入 // 约束:if(value==-1) // fputc(ch, fp); // 通过键盘输入方式存字符 char ch; while (1) { scanf("%c", &ch); // 输入@关闭文件 if (ch == \'@\') { break; } fputc(ch, fp); } // 关闭文件 fclose(fp); return 0; }
二、文件结尾
1、概述
在C语言中,EOF表示文件结束符(end of file)。在while循环中以EOF作为文件结束标志,这种以EOF作为文件结束标志的文件,必须是文本文件。在文本文件中,数据都是以字符的ASCII代码值的形式存放。我们知道,ASCII代码值的范围是0~127,不可能出现-1,因此可以用EOF作为文件结束标志。
#define EOF (-1)
当把数据以二进制形式存放到文件中时,就会有-1值的出现,因此不能采用EOF作为二进制文件的结束标志。为解决这一个问题,ANSI C提供一个feof函数,用来判断文件是否结束。feof函数既可用以判断二进制文件又可用以判断文本文件。
2、说明
#include <stdio.h>
int feof(FILE * stream);
功能:检测是否读取到了文件结尾。判断的是最后一次“读操作的内容”,不是当前位置内容(上一个内容)。
参数:
- stream:文件指针
返回值:
- 非0值:已经到文件结尾
- 0:没有到文件结尾
3、案例
略
三、读文件
1、说明
#include <stdio.h>
int fgetc(FILE * stream);
功能:从stream指定的文件中读取一个字符
参数:
- stream:文件指针
返回值:
- 成功:返回读取到的字符
- 失败:-1
2、案例
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <time.h> int main(void) { FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r"); if (!fp) { printf("打开文件失败\n"); return -1; } // 定义字符 char ch; // 文件字符读取 // 文件默认结尾为 -1 // ch = fgetc(fp); // 不能修改文件指针 // 文件在读取时光标流会自动向下移动 // fp++; // 循环打印 while ((ch = fgetc(fp)) != EOF) { printf("%c", ch); } // 关闭文件 fclose(fp); return 0; }
四、案例
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <time.h> int main(void) { FILE* fp1 = fopen("C:/Users/Administrator/Desktop/解密.txt", "r"); FILE* fp2 = fopen("C:/Users/Administrator/Desktop/加密.txt", "w"); if (!fp1 || !fp2)return -1; char ch; while ((ch = fgetc(fp1)) != EOF) { // 加密 ch++; fputc(ch, fp2); } fclose(fp1); fclose(fp2); return 0; }
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <time.h> int main(void) { FILE* fp1 = fopen("C:/Users/Administrator/Desktop/加密.txt", "r"); FILE* fp2 = fopen("C:/Users/Administrator/Desktop/解密文件.txt", "w"); if (!fp1 || !fp2)return -1; char ch; while ((ch = fgetc(fp1)) != EOF) { // 解密 ch--; fputc(ch, fp2); } fclose(fp1); fclose(fp2); return 0; }
文件行读写
一、写文件
1、说明
#include <stdio.h> int fputs(const char * str, FILE * stream);
功能:将str所指定的字符串写入到stream指定的文件中,字符串结束符 \'\0\' 不写入文件。
参数:
- str:字符串
- stream:文件指针
返回值:
- 成功:0
- 失败:-1
2、案例
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <time.h> int main(void) { // 打开文件 FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "w"); // 判断 if (!fp)return -1; // 创建字符串 // "你想怎\0么滴吧" 遇到\0则停止 // char ch[] = "你想怎么滴吧"; //fputs(ch, fp); // 通过键盘输入获取字符串 char* p = (char*)malloc(sizeof(char) * 1024); while (1) { memset(p, 0, 1024); // 问题:scanf("%s", p);无法接收回车空格 // 方式一、fgets() 可接收空格 // 方式二、scanf("%[^\n]", p); 避免吞噬空格回车 scanf("%[^\n]", p); // 吞噬回车\n getchar(); // 停止输入命令:comm=exit if (!strcmp(p, "comm=exit",9))break; // 追加换行符 strcat(p, "\n"); // 写入字符串 fputs(p, fp); } free(p); fclose(fp); return 0; }
二、读文件
1、说明
#include <stdio.h> char * fgets(char * str, int size, FILE * stream);
功能:从stream指定的文件内读入字符,保存到str所指定的内存空间,直到出现换行字符、读到文件结尾或是已读了size - 1个字符为止,最后会自动加上字符 \'\0\' 作为字符串结束。
参数:
- str:字符串
- size:指定最大读取字符串的长度(size - 1)
- stream:文件指针
返回值:
- 成功:成功读取的字符串
- 读到文件尾或出错: NULL
2、案例
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <time.h> int main(void) { // 打开文件 FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r"); // 判断 if (!fp)return -1; // 开辟堆空间 char* p = (char*)malloc(sizeof(char) * 1024); // 初始化内存空间 // memset(p, 0, 5); // 通过堆开放内存,打印文件中100个字节 // 根据光标位置继续向下读取字符串 // fgets(p, 5, fp); // printf("%s", p); // 打印 // feof(文件指针):判断文件是否到结尾 可以判断文本文件也可以判断二进制文件 // 如果到文件结尾返回值为 非0的值 // 如果没到文件结尾返回值为 0的值 while (!feof(fp)) { memset(p, 0, 100); fgets(p, 100, fp); printf("%s", p); } free(p); fclose(fp); return 0; }
三、案例
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <time.h> enum opt { add,sub,mlt,dive }; int main(void) { srand((size_t)time(NULL)); // 打开文件 FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "w"); // 判断 if (!fp)return -1; int a, b; char c; // + - * / char * p = (char*)malloc(sizeof(char) * 20); for (int i = 0; i < 100; i++) { a = rand() % 10 + 1; b = rand() % 10 + 1; switch (rand() % 4) { case add:c = \'+\';break; case sub:c = \'-\';break; case mlt:c = \'*\';break; case dive:c = \'/\';break; } memset(p, 0,20); sprintf(p, "%d%c%d=\n", a, c, b); fputs(p, fp);//fgets(p,size,fp) } free(p); fclose(fp); p = NULL; fp = NULL; return 0; }
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <time.h> int main(void) { srand((size_t)time(NULL)); // 打开文件 FILE* fp1 = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r"); FILE* fp2 = fopen("C:/Users/Administrator/Desktop/xsk2.txt", "w"); // 判断 if (!fp1 || !fp2)return -1; // 判断文件结尾 // !feof(fp); // EOF -1 int a, b, sum; char c; char * p = (char*)malloc(sizeof(char) * 20); for (int i = 0; i < 100; i++) { memset(p, 0, 20); // 打印1行内容 fgets(p, 20, fp1); sscanf(p, "%d%c%d=\n", &a, &c, &b); switch (c) { case \'+\':sum = a + b; break; case \'-\':sum = a - b; break; case \'*\':sum = a * b; break; case \'/\':sum = a / b; break; } memset(p, 0, 20); sprintf(p, "%d%c%d=%d\n", a, c, b, sum); fputs(p, fp2); } free(p); fclose(fp1); fclose(fp2); return 0; }
文件格式化
一、写文件
1、说明
#include <stdio.h> int fprintf(FILE * stream, const char * format, ...);
功能:根据参数format字符串来转换并格式化数据,然后将结果输出到stream指定的文件中,指定出现字符串结束符 \'\0\' 为止。
参数:
- stream:已经打开的文件
- format:字符串格式,用法和printf()一样
返回值:
- 成功:实际写入文件的字符个数
- 失败:-1
2、案例
略
二、读文件
1、说明
#include <stdio.h> int fscanf(FILE * stream, const char * format, ...);
功能:从stream指定的文件读取字符串,并根据参数format字符串来转换并格式化数据。
参数:
- stream:已经打开的文件
- format:字符串格式,用法和scanf()一样
返回值:
- 成功:参数数目,成功转换的值的个数
- 失败: - 1
2、案例
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <time.h> int main(void) { // 打开文件 FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r"); // 判断 if (!fp)return -1; char * p = (char*)malloc(sizeof(char) * 100); // 直接格式化取出字符串 // 遇到空格与回车就结束 // fscanf(fp, "%s", p); // printf("%s", p); int a, b, c; // 1+2=3 // 处理表达式 fscanf(fp, "%d+%d=%d", &a,&b,&c); printf("%d\n", a); printf("%d\n", b); printf("%d\n", c); free(p); fclose(fp); return 0; }
三、案例
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <time.h> int main(void) { srand((size_t)time(NULL)); // 打开文件 FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk1.txt", "w"); // 判断 if (!fp)return -1; int a, b; char c; for (int i = 0; i < 100; i++) { a = rand() % 10 + 1; b = rand() % 10 + 1; switch (rand() % 4) { case 0:c = \'+\'; break; case 1:c = \'-\'; break; case 2:c = \'*\'; break; case 3:c = \'/\'; break; } fprintf(fp, "%d%c%d=\n", a, c, b); } fclose(fp); return 0; }
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <time.h> int main(void) { srand((size_t)time(NULL)); // 打开文件 FILE* fp1 = fopen("C:/Users/Administrator/Desktop/xsk1.txt", "r"); FILE* fp2 = fopen("C:/Users/Administrator/Desktop/xsk2.txt", "w"); // 判断 if (!fp1||!fp2)return -1; int a, b, sum; char c; for (int i = 0; i < 100; i++) { fscanf(fp1, "%d%c%d\n", &a, &c, &b); switch (c) { case \'+\':sum = a + b; break; case \'-\':sum = a - b; break; case \'*\':sum = a * b; break; case \'/\':sum = a / b; break; } fprintf(fp2, "%d%c%d=%d\n", a, c, b,sum); } fclose(fp1); fclose(fp2); return 0; }
#include <stdlib.h> #include <math.h> #include <time.h> int main(void) { // 大文件排序 打印1000数字 srand((size_t)time(NULL)); // 打开文件 FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "w"); // 判断 if (!fp)return -1; for (int i = 0; i < 1000; i++) { fprintf(fp, "%d\n", rand() % 256); } fclose(fp); return 0; }
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <time.h> int main(void) { // 打开文件 FILE* fp1 = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r"); FILE* fp2 = fopen("C:/Users/Administrator/Desktop/xsk2.txt", "w"); // 判断 if (!fp1||!fp2)return -1; int* arr = (int*)malloc(sizeof(int) * 256); memset(arr, 0, sizeof(int) * 256); // 直接插入 // 数据一定要在一个范围内 for (int i = 0; i < 1000; i++) { int value; fscanf(fp1, "%d\n", &value); // 数据的个数放在对应的下标 arr[value]++; } for (int i = 0; i < 256; i++) { for (int j = 0; j < arr[i]; j++) { fprintf(fp2, "%d\n", i); } } free(arr); fclose(fp1); fclose(fp2); return 0; }
文件块读写
一、写文件
1、说明
#include <stdio.h> 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
2、案例
typedef struct Stu { char name[50]; int id; }Stu; Stu s[3]; int i = 0; for (i = 0; i < 3; i++) { sprintf(s[i].name, "stu%d%d%d", i, i, i); s[i].id = i + 1; } int ret = fwrite(s, sizeof(Stu), 3, fp); printf("ret = %d\n", ret);
二、读文件
1、说明
#include <stdio.h> 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
2、案例
typedef struct Stu { char name[50]; int id; }Stu; Stu s[3]; int ret = fread(s, sizeof(Stu), 3, fp); printf("ret = %d\n", ret); int i = 0; for (i = 0; i < 3; i++) { printf("s = %s, %d\n", s[i].name, s[i].id); }
三、案例
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <time.h> int main(void) { // 写入数据 // FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "wb"); // 判断 // if (!fp)return -1; // int a = 5678; // 以二级制格式写入 // fwrite(&a, sizeof(int), 1, fp); // fclose(fp); // 数组写入 // FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "wb"); // 判断 // if (!fp)return -1; // int arr[] = { 1,2,3,4,5,6,7,8,10 }; // fwrite(arr, sizeof(int), 10, fp); // fclose(fp); // 读取数据 // FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "rb"); // 判断 // if (!fp)return -1; // int value; // fread(&value, sizeof(int), 1, fp); // printf("%d\n", value); // fclose(fp); // 数组读取 // FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "rb"); // 判断 // if (!fp)return -1; // int arr[10] = { 0 }; // fread(arr, sizeof(int), 10, fp); // for (int i = 0; i < 10; i++) // { // printf("%d\n", arr[i]); // } return 0; }
文件随机读写
一、说明
#include <stdio.h> int fseek(FILE *stream, long offset, int whence);
功能:移动文件流(文件光标)的读写位置。
参数:
- stream:已经打开的文件指针
- offset:根据whence来移动的位移数(偏移量),可以是正数,也可以负数,如果正数,则相对于whence往右移动,如果是负数,则相对于whence往左移动。如果向前移动的字节数超过了文件开头则出错返回,如果向后移动的字节数超过了文件末尾,再次写入时将增大文件尺寸。
- whence:其取值如下:
- SEEK_SET:从文件开头移动offset个字节
- SEEK_CUR:从当前位置移动offset个字节
- SEEK_END:从文件末尾移动offset个字节
返回值:
- 成功:0
- 失败:-1
二、案例
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <time.h> int main(void) { FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r"); if (!fp) { return -1; } char arr[100]; // 输出第一行 memset(arr, 0, 100); fgets(arr, 100, fp); printf("%s", arr); // 输出第二行 memset(arr, 0, 100); fgets(arr, 100, fp); printf("%s", arr); // 光标偏移 // 文件随机读写 // 从当前位置偏移,往回偏移8个 fseek(fp, -8, SEEK_CUR); // 输出从光标位置输出 memset(arr, 0, 100); fgets(arr, 100, fp); printf("%s", arr); fclose(fp); return 0; }
#include <stdlib.h> #include <math.h> #include <time.h> int main(void) { FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "r+"); if (!fp) { return -1; } // 从文件末尾追加 fseek(fp,-1, SEEK_END); fputs("aaaa",fp); fclose(fp); return 0; }
文件流
一、文件流获取
1、说明
#include <stdio.h>
long ftell(FILE *stream);
功能:获取文件流(文件光标)的读写位置。
参数:
- stream:已经打开的文件指针
返回值:
- 成功:当前文件流(文件光标)的读写位置
- 失败:-1
2、案例
#include <string.h> #include <stdlib.h> #include <math.h> #include <time.h> int main(void) { FILE* fp = fopen("C:/Users/Administrator/Desktop/xsk.txt", "a"); if (!fp) { return -1; } // 查看当前位置 long pos = ftell(fp); printf("%ld\n", pos); fclose(fp); return 0; }
二、文件流修改
1、说明
#include <stdio.h>
void rewind(FILE *stream);
功能:把文件流(文件光标)的读写位置移动到文件开头。
参数:
- stream:已经打开的文件指针
返回值:
无返回值
2、案例
typedef struct Stu { char name[50]; int id; }Stu; //假如已经往文件写入3个结构体 //fwrite(s, sizeof(Stu), 3, fp); Stu s[3]; Stu tmp; int ret = 0; //文件光标读写位置从开头往右移动2个结构体的位置 fseek(fp, 2 * sizeof(Stu), SEEK_SET); //读第3个结构体 ret = fread(&tmp, sizeof(Stu), 1, fp); if (ret == 1) { printf("[tmp]%s, %d\n", tmp.name, tmp.id); } //把文件光标移动到文件开头 //fseek(fp, 0, SEEK_SET); rewind(fp); ret = fread(s, sizeof(Stu), 3, fp); printf("ret = %d\n", ret); int i = 0; for (i = 0; i < 3; i++) { printf("s === %s, %d\n", s[i].name, s[i].id); }
文件状态
一、说明
#include <sys/types.h> #include <sys/stat.h> int stat(const char *path, struct stat *buf);
功能:获取文件状态信息
参数:
- path:文件名
- buf:保存文件信息的结构体
返回值:
- 成功:0
- 失败-1
二、使用
struct stat { dev_t st_dev; //文件的设备编号 ino_t st_ino; //节点 mode_t st_mode; //文件的类型和存取的权限 nlink_t st_nlink; //连到该文件的硬连接数目,刚建立的文件值为1 uid_t st_uid; //用户ID gid_t st_gid; //组ID dev_t st_rdev; //(设备类型)若此文件为设备文件,则为其设备编号 off_t st_size; //文件字节数(文件大小) unsigned long st_blksize; //块大小(文件系统的I/O 缓冲区大小) unsigned long st_blocks; //块数 time_t st_atime; //最后一次访问时间 time_t st_mtime; //最后一次修改时间 time_t st_ctime; //最后一次改变时间(指属性) };
三、案例
#include <sys/types.h> #include <sys/stat.h> #include <stdio.h> int main(int argc, char **args) { if (argc < 2) return 0; // 文件状态结构体变量 struct stat st = { 0 }; stat(args[1], &st); int size = st.st_size;//得到结构体中的成员变量 printf("%d\n", size); return 0; }
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <time.h> #include <sys/types.h> #include <sys/stat.h> #define MAX (1024*1024*8) // 拷贝大文件 int main(int argc,char* argv[]) { // 显示参数内容 //for (int i = 0; i < argc; i++) //{ // printf("%s\n", argv[i]); //} // 用户输入参数缺少 if (argc < 3) { printf("缺少参数\n"); return -1; } // C:/copy.exe C:/xsk.txt C:/xsk/xsk.txt // argv[0] 程序名称、文件大小是50M FILE* fp1 = fopen(argv[1], "rb"); FILE* fp2 = fopen(argv[2], "wb"); if (!fp1 || !fp2) { printf("赋值文件出错\n"); return -2; } char* temp = NULL; int size = 0; // 求文件大小 struct stat st; stat(argv[1], &st); // 根据文件实际大小开辟空间 if (st.st_size > MAX) { temp = (char*)malloc(sizeof(char) * MAX); size = MAX; } else { temp = (char*)malloc(sizeof(char) * st.st_size + 10); size = st.st_size + 10; } // 接收每次读取的字节数 int count = 0; while (!feof(fp1)) { memset(temp, 0, size); // count=读取实际字节数、读取内容 count = fread(temp, sizeof(char), size,fp1); // 根据字节大小写入 fwrite(temp, sizeof(char), count, fp2); } free(temp); fclose(fp1); fclose(fp2); return 0; }
文件删除
一、说明
#include <stdio.h> int remove(const char *pathname);
功能:删除文件
参数:
- pathname:文件名
返回值:
- 成功:0
- 失败:-1
二、案例
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <time.h> int main(void) { // 删除文件 int value = remove("C:/Users/Administrator/Desktop/xsk.txt"); if (value == 0) { printf("删除成功\n"); } else { printf("删除失败\n"); } return 0; }
文件剪切重命名
一、说明
#include <stdio.h> int rename(const char *oldpath, const char *newpath);
功能:把oldpath的文件名改为newpath
参数:
- oldpath:旧文件名
- newpath:新文件名
返回值:
- 成功:0
- 失败: - 1
二、案例
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <time.h> int main(void) { // 重命名、移动文件 int value = rename("C:/Users/Administrator/Desktop/xsk.txt","C:/Users/Administrator/Desktop/xsk_new.txt"); if (value == 0) { printf("改名成功\n"); } else { printf("改名失败\n"); } return 0; }