【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;
}
相关推荐
xiaomo22492 小时前
javaee-网络原理(理论)
linux·服务器·网络
炘爚2 小时前
Linux 进程管理 GCC/GDB 编译调试
linux·运维·服务器
不想好好取名字2 小时前
Ubuntu apt启用dbg符号库
linux·运维·ubuntu
JiMoKuangXiangQu2 小时前
Linux:EtherCAT IgH 适配笔记
linux·ethercat igh
计算机安禾2 小时前
【数据结构与算法】第8篇:线性表(四):双向链表与循环链表
c语言·开发语言·数据结构·c++·算法·链表·visual studio
刚入门的大一新生7 小时前
Linux-Linux的基础指令4
linux·运维·服务器
WalterJau11 小时前
C 内存分区
c语言
路溪非溪12 小时前
Linux下蓝牙框架的数据流
linux·arm开发·驱动开发
能不能别报错12 小时前
openclaw-linux部署教程+mimo-v2-pro
linux·运维·服务器