C语言 文件操作(对内容增删改查)
目录
1. 概述
磁盘文件:指一组相关数据的有序集合,通常存储在外部介质(如磁盘)上,使用时才调入内存。
设备文件:把操作系统中把每一个与主机相连的输入、输出设备看作是一个文件,把它们的输入、输出等同于对磁盘文件的读和写。
计算机的存储在物理上是二进制的,以字节为单位进行顺序存储。
从用户或者操作系统使用的角度把文件分为:
- 文本文件:基于字符编码(ASCII、UNICODE等)的文件
- 二进制文件:基于值编码的文件
2. 文件指针
在c语言中用一个指针变量指向一个文件,这个指针称为文件指针。
- FILE *p
- 当我们使用C库函数fopen打开一个文件,它会返回一个指向该文件所有信息的指针。
3. 文件打开
fopen(const char *path, char *mode)
mode: 文件打开方式()
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
FILE* fp = NULL;
fp = fopen("test.txt", "w");// 不存在会新建,存在就清空
if (fp == NULL) {
perror("fopen");
return -1;
}
return 0;
}
4. 文件关闭
总是打开会消耗很多内存,要及时关闭。
int fclose(FILE* stream):返回0,表示失败;返回1,表示成功
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
FILE* fp = NULL;
fp = fopen("test.txt", "w");// 不存在会新建,存在就清空
if (fp == NULL) {
perror("fopen");
return -1;
}
fclose(fp);
return 0;
}
5. fputc的使用
int fputc(int ch, FILE* fp):ch是写入的字符,会转换成unsigned char类型再写入;fp是文件指针
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
FILE* fp = NULL;
fp = fopen("test.txt", "w");
// 1. 字符
char buf[] = "this is a file";
int n = sizeof(buf) / sizeof(buf[0]);
int ch;
for (int i = 0; i < n; i++) {
ch = fputc(buf[i], fp);
printf("%c", buf[i]);
}
fclose(fp);
return 0;
}
不过这里查看的话,是乱码
6. fgetc和feof的使用
int feof(FILE* stream):检测是否读取到了文件结尾。
int feof(FILE* stream):到文件结束,非0,没到为0
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
FILE* fp = NULL;
fp = fopen("test.txt", "r");
char ch;
while (1) {
ch = fgetc(fp);
//if (ch == EOF) {// 判断文本文件结束符号。对二进制文件不能这么判断
if(feof(fp) != 0){// 可以判断文本文件和二进制的文件
break;
}
putchar(ch);
}
fclose(fp);
return 0;
}
输出结果:
this is a file
C:\Users\YUEXU\source\repos\CTest\x64\Debug\CTest.exe (进程 21136)已退出,代码为 0 (0x0)。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
7. fputs和fgets使用
int fputs(const char *str, FILE* stream):将str所指定的字符串写入stream指定的文件中,字符串结束符"\0"不写入文件
int fgets(char *str,int size, FILE* stream):从stream指定文件中读入字符,保存到str所指定的内存空间,知道出现换行字符、读到文件结尾或是已读了size - 1 个字符为止,最后自动会加上字符'\0'
作为字符串结尾
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main(){
char* buf[] = {"hello world\n","haha\n"};
int n = sizeof(buf) / sizeof(buf[0]);
FILE* fp = NULL;
fp = fopen("test.txt", "w");
if (fp == NULL) {
perror("fopen");
return -1;
}
for (int i = 0; i < n; i++) {
fputs(buf[i], fp);
}
fclose(fp);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
char buf[100] = { 0 };
FILE* fp = NULL;
fp = fopen("test.txt", "r");
if (fp == NULL) {
perror("fopen");
return -1;
}
while (feof(fp) == 0) {
memset(buf, 0, sizeof(buf));
fgets(buf, sizeof(buf), fp);
printf("buf = %s\n", buf);
}
fclose(fp);
return 0;
}
8. 格式化文件fprintf、fscanf
int fprintf(FILE* stream, const char* format, …):根据参数format字符串来转换并格式化数据,然后将结果输出到stream指定的文件中,指定出现字符串结束符'\0'
为止。
int fscanf(FILE* stream, const char* format, …):从stream指定的文件读取字符串,并根据参数format字符串来转换并格式化数据。
格式化写入文件:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main() {
FILE* fp = NULL;
fp = fopen("b.txt", "w");
if (fp == NULL) {
perror("fopen");
return - 1;
}
fprintf(fp, "%d %d, %d", 10, 20, 30);
fclose(fp);
return 0;
}
格式化读取文件:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main() {
FILE* fp = NULL;
fp = fopen("b.txt", "r");
if (fp == NULL) {
perror("fopen");
return -1;
}
int a, b, c;
fscanf(fp, "%d %d, %d", &a, &b, &c);
printf("%d %d, %d\n", a, b, c);
fclose(fp);
return 0;
}
输出结果:
10 20, 30
C:\Users\YUEXU\source\repos\CTest\x64\Debug\CTest.exe (进程 27244)已退出,代码为 0 (0x0)。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
9. 文件块读写操作fread和fwrite
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE* stream):以数据块的方式给文件写入内容。
size_t fread(void *ptr, size_t size, size_t nmemb, FILE* stream):以数据块的方式给文件写入内容。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct stu {
char name[30];
int id;
}STU;
int main() {
STU s[3] = { 0 };
for (int i = 0; i < 3;i++) {
sprintf(s[i].name, "stu%d%d%d", i, i, i);
s[i].id = i + 1;
}
FILE* fp = NULL;
fp = fopen("b.txt", "w");
if (fp == NULL) {
perror("fopen");
return -1;
}
// 1. 块操作写文件
int ret;
ret = fwrite(s, sizeof(STU), 3, fp);
printf("ret = %d\n", ret);
// 2. 块操作读文件
STU s2[3];
fread(s2, sizeof(STU), 3, fp);
for (int i = 0; i < 3;i++) {
printf("s:%s,%d\n", s[i].name, s[i].id);
}
fclose(fp);
return 0;
}
运行结果:
ret = 3
s:stu000,1
s:stu111,2
s:stu222,3
C:\Users\YUEXU\source\repos\CTest\x64\Debug\CTest.exe (进程 21964)已退出,代码为 0 (0x0)。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
10. 文件的随机读取
int fseek(FILE* stream, long offset, int whence):移动文件流(文件光标)的读写位置。offset是偏移量,whence的取值,SEEK_SET(从文件开头),SEEK_CUR(当前位置),SEEK_END(末尾)。
int ftell(FILE* stream):获取文件流(光标位置)的读取位置。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct stu {
char name[30];
int id;
}STU;
int main() {
FILE* fp = NULL;
fp = fopen("b.txt", "r");
if (fp == NULL) {
perror("fopen");
return -1;
}
int offset = ftell(fp);
printf("文件当前偏移量:%d\n", offset);
STU s3;
fseek(fp, sizeof(STU) * 2, SEEK_SET);
offset = ftell(fp);
printf("文件当前偏移量:%d\n", offset);
int ret = fread(&s3, sizeof(STU), 1, fp);
if (ret == 1) {
printf("第三个结构体:s:%s,%d\n", s3.name, s3.id);
}
offset = ftell(fp);
printf("文件当前偏移量:%d\n", offset);
return 0;
}
输出结果:
文件当前偏移量:0
文件当前偏移量:72
第三个结构体:s:stu222,3
文件当前偏移量:108
C:\Users\YUEXU\source\repos\CTest\x64\Debug\CTest.exe (进程 4224)已退出,代码为 0 (0x0)。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
11. 获取文件状态
#include<sys/types.h>
#include<sys/stat.h>
int stat(const char *path, struct stat *buf):获取文件状态信息。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<sys/types.h>
int main(int argc, char* argv[]) {
if (argc != 2) {
printf("用法:xxx.exe 文件名\n");
return -1;
}
struct stat s = { 0 };
stat(argv[1], &s);
printf("文件大小:%d\n", s.st_size);
return 0;
}
在该文件的路径打开终端,cmd
输入命令:
gcc 该文件.c -o test
输入:
test.exe b.txt
输出结果:
文件大小:216
12. 删除文件、重命名文件
remove(文件名)
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(int argc, char* argv[]) {
if (argc != 2) {
printf("用法:xxx.exe 需要删除文件名\n");
return -1;
}
remove(argv[1]);
return 0;
}
终端编译,
输入命令:
dir
输出结果:
驱动器 C 中的卷没有标签。
卷的序列号是 C14D-581B
C:\Users\YUEXU\source\repos\CTest 的目录
2024/11/24 17:28 <DIR> .
2024/11/14 00:16 <DIR> ..
2024/11/24 17:02 216 b.txt
2024/11/14 00:25 <DIR> CTest
2024/11/15 00:05 1,312 CTest.aps
2024/11/14 00:27 868 CTest.cpp
2024/11/15 00:05 2,462 CTest.rc
2024/11/14 00:16 1,429 CTest.sln
2024/11/23 23:29 7,045 CTest.vcxproj
2024/11/23 23:29 1,852 CTest.vcxproj.filters
2024/11/16 01:28 389 CTest.vcxproj.user
2024/11/22 00:55 964 CTest1.c
2024/11/15 00:08 150 func.c
2024/11/14 23:22 50 func.h
2024/11/15 00:05 384 resource.h
2024/11/24 17:28 54,197 test.exe
2024/11/24 01:35 19 test.txt
2024/11/14 00:25 <DIR> x64
2024/11/24 17:27 3,758 文件操作.c
2024/11/23 23:27 2 文件操作.h
2024/11/23 23:26 4,181 结构体.c
2024/11/22 00:54 2 结构体.h
18 个文件 79,280 字节
4 个目录 51,060,375,552 可用字节
输入命令:
test.exe test.txt
dir
输出结果:
驱动器 C 中的卷没有标签。
卷的序列号是 C14D-581B
C:\Users\YUEXU\source\repos\CTest 的目录
2024/11/24 17:28 <DIR> .
2024/11/14 00:16 <DIR> ..
2024/11/24 17:02 216 b.txt
2024/11/14 00:25 <DIR> CTest
2024/11/15 00:05 1,312 CTest.aps
2024/11/14 00:27 868 CTest.cpp
2024/11/15 00:05 2,462 CTest.rc
2024/11/14 00:16 1,429 CTest.sln
2024/11/23 23:29 7,045 CTest.vcxproj
2024/11/23 23:29 1,852 CTest.vcxproj.filters
2024/11/16 01:28 389 CTest.vcxproj.user
2024/11/22 00:55 964 CTest1.c
2024/11/15 00:08 150 func.c
2024/11/14 23:22 50 func.h
2024/11/15 00:05 384 resource.h
2024/11/24 17:28 54,197 test.exe
2024/11/14 00:25 <DIR> x64
2024/11/24 17:27 3,758 文件操作.c
2024/11/23 23:27 2 文件操作.h
2024/11/23 23:26 4,181 结构体.c
2024/11/22 00:54 2 结构体.h
17 个文件 79,261 字节
4 个目录 51,060,224,000 可用字节
很明显,test.txt删除了
重命名:rename(文件名,文件名)
总结
这块是基本操作,没有很难很深的东西,so easy!!!
原文地址:https://blog.csdn.net/weixin_51395608/article/details/144000902
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!