【C语言】Linux系统文件操作函数基本使用

Linux系统文件操作函数

包含:open close read write lseek fcntl

是Linux底层提供的API,直接和系统内核交互:

  • 无缓冲区
  • 直接操作文件描述符
  • 一切皆文件:普通文件、目录、设备、管道、socket都用这一套函数

! 说明

文件描述符

文件描述符是一个非负的整数,表示Linux内核打开的文件;

启动一个进程,默认打开三个文件描述符[0-2]

每次打开一个文件,系统分配一个最小的文件描述符;

内核里有一张表:进程 -> 文件描述符表 -> 指向文件结构体

需要包含的头文件:

c 复制代码
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> // open 
#include <unistd.h> // read, write, close, lseek 
#include <errno.h> // 错误码

6.1 open - 打开/创建文件

函数原型:

c 复制代码
int open(const char *pathname, int flags, mode_t mode);

作用

打开或创建一个文件,返回 文件描述符 fd (小整数)。
flags(必须掌握)

  • O_RDONLY 只读
  • O_WRONLY 只写
  • O_RDWR 读写
  • O_CREAT 文件不存在则创建
  • O_TRUNC 清空文件
  • O_APPEND 追加模式
  • O_NONBLOCK 非阻塞
  • O_BINARY 二进制(Linux 可省略)
  • O_EXCL 和 O_CREAT 一起用:文件存在则报错 (防止覆盖)
    mode(创建文件时用,权限)
    格式:0xxx 8 进制数字
  • 0644 所有者读写,其他只读
  • 0755 可执行文件
    返回值
  • 成功:文件描述符 fd(>=0)
  • 失败:-1
    示例:
c 复制代码
#include <stdio.h>
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> // open 
#include <unistd.h> // read, write, close, lseek 
#include <errno.h> // 错误码

int main()
{
	// 以只写方式发开文件,不存在则创建,权限644
	int fd = open("test.txt", O_WRONLY | O_CREAT, 0644);
	
	// 判断是否成功,open失败返回-1
	if(fd == -1){
		perror("open:");
		return -1;
	}	
	
	// 关闭文件
	close(fd);
	return 0;
}

6.2 close - 关闭文件

关闭文件描述符,释放资源。

c 复制代码
int close(int fd);

返回值

  • 成功:0
  • 失败:-1

6.3 write - 写文件

把 buf 中的数据写入文件。

c 复制代码
ssize_t write(int fd, const void *buf, size_t count);

返回值

  • 成功:实际写入字节数
  • 失败:-1
    示例:
c 复制代码
#include <stdio.h>
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> // open 
#include <unistd.h> // read, write, close, lseek 
#include <errno.h> // 错误码
#include <string.h>

int main()
{

	int fd = open("test.txt", O_WRONLY | O_CREAT, 0644);
	if(fd == -1){
		perror("open:");
		return -1;
	}	


	// 写文件
	char buff[] = "你好,C!";
	
	// 返回写入的实际字节数
	int ret = write(fd, buff, strlen(buff));

	printf("write size = %d\n", ret);

	close(fd);

	return 0;
}

6.4 read - 读文件

从 fd 读取数据到缓冲区。

c 复制代码
ssize_t read(int fd, void *buf, size_t count);

参数

fd:文件描述符

buf:存储读到的数据

count:期望读多少字节
返回值

  • 0:实际读到的字节数

  • =0:读到文件末尾(EOF)
  • -1:出错
    示例:
c 复制代码
#include <stdio.h>
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> // open 
#include <unistd.h> // read, write, close, lseek 
#include <errno.h> // 错误码
#include <string.h>

int main()
{
	// 以只读方式打开文件
	int fd = open("test.txt", O_RDONLY);
	if(fd == -1){
		perror("open:");
		return -1;
	}	


	// 读文件
	char buff[1024] = {'\0'};
	int ret = read(fd, buff, 1024); 

	printf("read size = %d, read info: %s\n", ret, buff);

	close(fd);
	return 0;
}

6.5 lseek - 移动文件的读写指针

定位文件读写位置(类似光标跳转)。

c 复制代码
off_t lseek(int fd, off_t offset, int whence);

whence

  • SEEK_SET 文件开始位置
  • SEEK_CUR 当前位置
  • SEEK_END 文件末尾

off_t offset 偏移量(正数向后,负数向前)

用途

  • 获取文件大小:lseek(fd, 0, SEEK_END)
  • 跳转到指定位置读写
    返回值
  • 成功:返回 新的光标位置(距离文件开头多少字节)
  • 失败:返回 -1
    用法:
  • 把光标移到 文件开头
c 复制代码
lseek(fd, 0, SEEK_SET);
  • 把光标移到 文件末尾
c 复制代码
lseek(fd, 0, SEEK_END);
  • 获取 文件大小(最经典用法)
c 复制代码
off_t size = lseek(fd, 0, SEEK_END); 
printf("文件大小:%ld 字节\n", size);
  • 扩展文件大小(创建空洞文件)
c 复制代码
// 把文件扩展到 1024 字节 
lseek(fd, 1024, SEEK_SET); 
write(fd, "a", 1); // 必须写一个字节才真正扩展

! 注意

  • read /write 会自动让光标向后移动,读多少字节,光标自动后移多少;
  • lseek 不会修改文件内容,只改光标位置;
  • 光标可以移到文件末尾之外 → 形成空洞文件
  • 管道、socket、终端设备 不能用 lseek(会报错)

示例:

c 复制代码
#include <stdio.h>
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> // open 
#include <unistd.h> // read, write, close, lseek 
#include <errno.h> // 错误码
#include <string.h>

int main()
{

	int fd = open("test.txt", O_RDWR | O_CREAT, 0644);
	if(fd == -1){
		perror("open:");
		return -1;
	}	


	// 写文件
	char buff[1024] = "Hello Rocky Linux!";
	int ret = write(fd, buff, 1024);	

	// 写文件会移动文件指针,将文件指针移动带开始位置再读取
	lseek(fd, 0, SEEK_SET);
	memset(buff, 0, 1024);	

	// 读文件
	ret = read(fd, buff, 1024); 

	printf("read size = %d, read info: %s\n", ret, buff);

	close(fd);
	return 0;
}
相关推荐
原来是猿7 小时前
网络计算器:理解序列化与反序列化(中)
linux·运维·服务器·网络·tcp/ip
知识领航员7 小时前
蘑兔AI音乐深度实测:功能拆解、实测表现与适用场景
java·c语言·c++·人工智能·python·算法·github
AOwhisky7 小时前
虚拟化技术学习笔记
linux·运维·笔记·学习·虚拟化技术
rabbit_pro8 小时前
Docker compose部署Ollama使用模型
linux·运维·docker
Irissgwe11 小时前
六、Ext系列文件系统(2.核心原理与应用)
linux·分区··inode·软硬连接·路径缓存·ext系列文件
tkevinjd11 小时前
wsl2安装
linux·wsl·虚拟机·wsl2
故事还在继续吗11 小时前
Linux 内核模块开发实战
linux·linux内核
南境十里·墨染春水12 小时前
linux学习进展 守护进程
linux·服务器·学习
程序leo源12 小时前
C语言知识总结
c语言·开发语言·c++·经验分享·笔记·青少年编程·c#
REDcker12 小时前
Android HWASan 详解:硬件标记原理、Clang 启用与排障实践
android·linux·debug·编译·clang·asan·hwasan