【Linux】C语言文件操作

1. FILE* 是什么

C 的文件操作都围绕 FILE *(文件指针)展开。fopen 返回它,之后所有读写都通过它指定目标文件。

程序启动时默认打开三个流,类型都是 FILE *:

cpp 复制代码
extern FILE *stdin;    // 标准输入(键盘)
extern FILE *stdout;   // 标准输出(显示器)
extern FILE *stderr;   // 标准错误(显示器)

所以 printf(...) 等价于 fprintf(stdout, ...)。

2. 打开方式

模式 含义 文件不存在 文件已存在
r 只读 返回 NULL 位置在开头
r+ 读 + 写 返回 NULL 不清空,位置在开头
w 只写 创建 清空
w+ 写 + 读 创建 清空
a 追加写 创建 不清空,写永远在末尾
a+ 追加写 + 读 创建 不清空,读从开头,写在末尾

+ 的含义就是"再加上另一种操作",有'+'的时候,同一个 FILE * 既能读也能写 。注意 w 和 w+ 打开已有文件会直接清空内容。

3. 基本流程

cpp 复制代码
FILE *fp = fopen("myfile", "w");
if (!fp) {
    perror("fopen");   // 必须检查返回值
    return 1;
}
// 读写...
fclose(fp);            // 用完必须关闭

如果写的是相对路径,系统会基于进程的当前工作目录(cwd)解析成绝对路径。

4. 写文件:fwrite

cpp 复制代码
const char *msg = "hello bit!\n";
fwrite(msg, strlen(msg), 1, fp);

参数依次是:数据地址、单个元素大小、元素个数、文件指针。

写 strlen(msg) 而不是 strlen(msg)+1,避免把 \0 写进文件。

'\0'是C语言的规定,与文件无关。不能直接把'\0'写进文件。

5. 读文件:fread

cpp 复制代码
char buf[1024];
size_t s = fread(buf, 1, sizeof(buf) - 1, fp);
if (s > 0) {
    buf[s] = 0;
    printf("%s", buf);
}
  • 返回值是实际读到的元素个数。元素大小为 1 时,等于字节数。
  • fread 不会补 \0 ,打印字符串前要手动 buf[s] = 0,所以读 sizeof(buf) - 1 留出一个位置,避免越界。

6. 位置指针(文件偏移量)

每个打开的文件都有一个"当前读写位置",是一个数字 ,表示读写到第几个字节。读和写共用同一个位置。

fp:指向文件对象,决定操作哪个文件

位置指针:记录读写到哪个位置 ,由 ftell 查看,fseek/rewind 修改

类比:fp 是书,位置指针是书签。

函数 作用
ftell(fp) 返回当前位置(距开头的字节数)
fseek(fp, offset, whence) 移动位置,whence 取 SEEK_SET / SEEK_CUR / SEEK_END
rewind(fp) 回到开头,等价于 fseek(fp, 0, SEEK_SET)

7. 为什么 w+ 写完要 rewind

写完后位置停在末尾,直接读后面没有内容:

cpp 复制代码
FILE *fp = fopen("myfile", "w+");
fwrite("hello\n", 1, 6, fp);
printf("%ld\n", ftell(fp));   // 6

rewind(fp);                   // 回到开头
printf("%ld\n", ftell(fp));   // 0

char buf[100];
size_t s = fread(buf, 1, 99, fp);   // 读到 6 字节

这不是 + 本身的特性,而是"读写共用一个位置"的结果。+ 只是让你能在同一个文件上先写后读。

另外 C 标准规定:同一个文件读写切换之间,必须调用 fflush 或定位函数(fseek、rewind),否则行为未定义。

相关推荐
say_fall2 小时前
【Linux系统编程】Ext 文件系统:磁盘与存储、文件与目录、现代计算机究竟如何寻找文件
linux·运维·服务器·数据库·c++
wacsii3 小时前
【Linux进程(一)】Linux 进程初探:操作系统如何管理进程?fork() 为什么返回两次?
linux·运维·服务器
AI+程序员在路上3 小时前
RV1126B 上支持的模型及全流程应用--从CNN及语音到 LLMVLM 与跨平台选型
linux·c语言·人工智能
默|笙3 小时前
【Linux网络】传输层协议TCP(1)---TCP报文介绍
linux·网络·tcp/ip
相思难忘成疾3 小时前
从零搭建 Kubernetes 1.30 集群:kubeadm 部署一主多从实战(RHEL 9.3 + Docker + flannel)
linux·运维·kubernetes
用户4107192013253 小时前
用 systemd 从零做一个系统健康巡检服务:脚本、沙箱与磁盘满排查实战
linux·ubuntu
GeW4 小时前
新质生产力路线图下,Linux 和数据库不能拆成两件事做
linux
云和数据.ChenGuang4 小时前
Python 闭包详解:从原理到实战
linux·开发语言·人工智能·python·kubernetes
Linux-lucky4 小时前
46-Linux学习之旅之LVS负载均衡与keepalived高可用
linux·运维·学习·ubuntu·负载均衡·lvs