自学内容网 自学内容网

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)!