news 2026/5/25 15:38:17

应用——文件I/O操作代码

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
应用——文件I/O操作代码

文件I/O操作代码分析

一、基础文件操作

1. 打开文件 -01open.c

#include <fcntl.h> #include <stdio.h> int main(int argc, char **argv) { int fd = open("1.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666); if (-1 == fd) { fprintf(stderr, "open error\n"); return 1; } return 0; }

知识点

  • open():系统调用打开文件

  • flags参数

    • O_WRONLY:只写模式

    • O_CREAT:文件不存在时创建

    • O_TRUNC:清空文件内容

  • mode参数0666表示文件权限(用户、组、其他都可读写)

  • 文件描述符:成功返回非负整数,失败返回-1

2. 写入文件 -04write.c

#include <fcntl.h> #include <stdio.h> int main(int argc, char **argv) { int fd = open("1.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666); char str[100] = "hello"; ssize_t ret = write(fd, str, strlen(str)); printf("写入了%ld字节到文件", ret); close(fd); return 0; }

知识点

  • write(fd, buf, count):写入数据

  • strlen(str)vssizeof(str)

    • strlen(str):实际字符串长度(不包括'\0')

    • sizeof(str):数组总大小(100字节)

  • ssize_t:有符号整数类型,表示实际写入字节数

  • 必须调用close(fd)释放资源

3. 读取文件 -05read.c

#include <fcntl.h> #include <stdio.h> int main(int argc, char **argv) { int fd = open("/etc/passwd", O_RDONLY); char buf[50] = {0}; while (1) { bzero(buf, sizeof(buf)); // 清空缓冲区 int ret = read(fd, buf, sizeof(buf)-1); // 留一个位置给'\0' if (ret <= 0) break; printf("[%d]:{%s}", ret, buf); } close(fd); return 0; }

知识点

  • read(fd, buf, count):读取数据

  • 缓冲区清空

    • bzero(buf, sizeof(buf)):将内存清零

    • memset(buf, 0, sizeof(buf)):功能相同

  • 读取策略sizeof(buf)-1保留一个字节给字符串结束符

  • 返回值

    • >0:实际读取字节数

    • =0:文件结束

    • <0:错误

4. 文件复制 -06read_cp.c

#include <fcntl.h> #include <stdio.h> int main(int argc, char **argv) { if (argc < 3) { printf("usage: ./a.out srcfile dstfile\n"); } int fd_src = open(argv[1], O_RDONLY); int fd_dst = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666); while (1) { char buffer[1024] = {0}; int ret = read(fd_src, buffer, sizeof(buffer)); if (ret <= 0) break; write(fd_dst, buffer, ret); } close(fd_dst); close(fd_src); return 0; }

知识点

  • 命令行参数argv[1]源文件,argv[2]目标文件

  • 分块读取:循环读取直到文件结束

  • 精确写入write(fd_dst, buffer, ret)只写入实际读取的字节

  • 资源管理:最后关闭两个文件描述符

二、高级文件操作

1. 文件插入 -02insert_file.c

#include <fcntl.h> #include <stdio.h> int main(int argc, char **argv) { FILE* fp = fopen("1.txt", "r+"); // 获取文件大小 fseek(fp, 0, SEEK_END); long size = ftell(fp); int pos = 15; char insert_str[100] = "hello"; // 保存后半部分内容 fseek(fp, pos, SEEK_SET); char *data = (char*)malloc(size); fread(data, size-pos, 1, fp); // 插入内容 fseek(fp, pos, SEEK_SET); fwrite(insert_str, strlen(insert_str), 1, fp); fwrite(data, size-pos, 1, fp); fclose(fp); free(data); return 0; }

知识点

  • 标准I/O:使用fopen()fread()fwrite()

  • 文件定位

    • fseek(fp, 0, SEEK_END):移动到文件末尾

    • ftell(fp):获取当前位置(即文件大小)

  • 插入策略

    1. 读取插入点之后的内容到内存

    2. 在插入点写入新内容

    3. 追加原来的后半部分内容

  • 内存管理:使用malloc()动态分配,最后free()

2. 文件定位 -08lseek.c

#include <fcntl.h> #include <stdio.h> int main(int argc, char **argv) { int fd = open("1.txt", O_RDWR); // 获取文件大小 long size = lseek(fd, 0, SEEK_END); printf("size %ld\n", size); // 移动到指定位置并写入 lseek(fd, 1024*1024, SEEK_SET); char str[] = "老孙到此一游"; write(fd, str, strlen(str)); close(fd); return 0; }

知识点

  • lseek(fd, offset, whence):移动文件指针

    • SEEK_SET:从文件开头

    • SEEK_CUR:从当前位置

    • SEEK_END:从文件末尾

  • 空洞文件:跳过大量字节后写入,中间部分会被填'\0'

  • 文件大小:使用lseek(fd, 0, SEEK_END)获取文件大小

三、标准输入输出

07stdin.c

#include <fcntl.h> #include <stdio.h> int main(int argc, char **argv) { char buf[10] = {0}; printf("pls input num:"); fflush(stdout); // 强制刷新缓冲区 read(0, buf, sizeof(buf)); // 从标准输入读取 int num = atoi(buf); write(2, &num, 4); // 写入标准错误 return 0; }

知识点

  • 标准文件描述符

    • 0:标准输入(stdin)

    • 1:标准输出(stdout)

    • 2:标准错误(stderr)

  • 缓冲机制

    • printf()输出到缓冲区,需要刷新才能显示

    • fflush(stdout)强制刷新输出缓冲区

  • 字符串转换atoi()将字符串转换为整数

  • 系统调用读写read()/write()也可以操作标准输入输出

四、应用实例

字典程序 -03dict.c

#include <stdio.h> #include <stdlib.h> #include <string.h> #include "list.h" typedef struct { char word[50]; char mean[512]; struct list_head node; } DATATYPE; int main(int argc, char** argv) { // 1. 打开字典文件 FILE* fp = fopen("/home/linux/dict.txt", "r"); // 2. 初始化链表 struct list_head dict_head; INIT_LIST_HEAD(&dict_head); // 3. 读取并存储字典数据 while (1) { char str[1024] = {0}; if (NULL == fgets(str, sizeof(str), fp)) break; char* word = strtok(str, " "); char* mean = strtok(NULL, "\r"); add_word(&dict_head, word, mean); } // 4. 用户查询交互 while (1) { char want_word[50] = {0}; printf("pls input want_word:"); fgets(want_word, sizeof(want_word), stdin); want_word[strlen(want_word) - 1] = '\0'; // 去掉换行符 if (0 == strcmp(want_word, "#quit")) break; DATATYPE* tmp = find_word(&dict_head, want_word); if (NULL == tmp) { printf("cant find word:%s\n", want_word); } else { printf("word:%s mean:%s\n", tmp->word, tmp->mean); } } return 0; }

核心知识点

  1. 文件读取

    • fgets(str, sizeof(str), fp):安全读取一行

    • 检查NULL判断文件结束// 原始格式:单词 解释\r\n

  2. char* word = strtok(str, " "); // 第一个空格前是单词 char* mean = strtok(NULL, "\r"); // 到\r前是解释 fgets(want_word, sizeof(want_word), stdin);
  3. want_word[strlen(want_word) - 1] = '\0'; // 去掉末尾的换行符
  4. 链表操作

    • list_add(&p->node, head):添加到链表

    • list_for_each_entry_safe():安全遍历链表

五、重要总结

1. 系统调用 vs 标准I/O

操作系统调用标准I/O
打开open()fopen()
读取read()fread()
写入write()fwrite()
关闭close()fclose()
定位lseek()fseek()

2. 常用文件打开模式

模式说明
O_RDONLY只读
O_WRONLY只写
O_RDWR读写
O_CREAT不存在时创建
O_TRUNC清空文件
O_APPEND追加模式

3. 错误处理模式

int fd = open("file.txt", O_RDONLY); if (-1 == fd) { perror("open failed"); // 自动添加错误信息 // 或 fprintf(stderr, "open error: %s\n", strerror(errno)); return 1; }

4. 内存与文件操作注意事项

  1. 缓冲区管理:读取前清空,写入时注意长度

  2. 资源释放:打开后必须关闭,分配后必须释放

  3. 错误检查:每个系统调用都可能失败

  4. 边界检查:防止缓冲区溢出

  5. 文件权限:创建文件时指定合适的权限

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!