【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;
}
相关推荐
Cyber4K16 小时前
【Nginx专项】基础入门篇-访问限制及访问控制
linux·运维·服务器·nginx
涛声依旧3931616 小时前
创建新的虚拟主机
linux·服务器·网络
itman30116 小时前
C语言printf输出格式:%d %f %s等用法详解
c语言·字符串·printf·格式化输出·整数
高斯的手稿080117 小时前
树莓派上更换镜像源的方法
linux·运维·windows
我不是懒洋洋17 小时前
【经典题目】链表OJ(相交链表、环形链表、环形链表II、随机链表的复制)
c语言·开发语言·数据结构·链表·ecmascript·visual studio
想拿大厂offer17 小时前
【Linux】常用指令
linux
うちは止水17 小时前
linux yocto bitbake构建系统生成SDK包
linux·sdk·yocto·bitbake
四禾子17 小时前
ubuntu的使用心得体会
linux·运维·ubuntu
学Linux的语莫17 小时前
vscode连接linux服务器,linux环境编程开发。
linux·vscode·ubuntu·编辑器
mounter62517 小时前
【深度解析】Device Memory TCP:开启高性能网络传输的“零拷贝”新时代
linux·服务器·网络·网络协议·tcp/ip·kernel·devmem