Linux——C语言文件IO(系统调用)

本文详细介绍了Linux环境下C语言通过系统调用实现的文件I/O操作,包括open(), read(), write(), 和 close()函数的使用,以及lseek()在字符串拷贝和文件复制中的应用。重点强调了正确处理文件偏移和文件描述符管理的重要性。
摘要由CSDN通过智能技术生成
Linux——C语言文件IO(系统调用)

运行环境:Ubuntu18.04

前言:
对于系统调用,我们对于文件IO需要学习的主要有open()、read()、write()、close()。我们平时使用的库函数其实都是通过系统调用进行封装成各种功能的函数。
1、open()
int open(const char *path, int oflag, mode)
path: 要打开的文件、设备的路径
oflag:
(1)必选:O_RDONLY(只读)、O_WRONLY(只写)、O_RDWR(读写)

(2)可选:O_APPEND 末尾写入
O_CREAT 文件不存在则创建它,使用该选项需要添加第三个参数;
O_TRUNC 如果文件存在,而且为只写或读写成功打开,则将其长度截取为0;相当于清空文件夹。

(3)mode:这个是指文件的权限,对应所有者、group、other的权限,对于普通文件一般为读写即可。
fd = open(“test.txt”, O_RDWR | O_CREAT | O_TRUNC ,0666)
fd = open(“test.txt”, O_RDWR | O_TRUNC )

(4)fd为文件描述符,相当于操作该文件对象的一个编号。

2、create()
int creat(const char *path, mode_t mode);
此函数用来创建一个新文件并返回其fd。
它等价于 open(path, O_WRONLY|O_CREAT|O_TRUNC, mode);

3、write()
ssize_t write(int fd, const void *buf, size_t nbytes);
(1)fd:写入数据的文件对象

(2)buf:将buf中的数据写入文件中。

(3)nbytes:指定要写入数据的大小,一般和读取的字符大小一致。

(4)返回值:如果 >0 则为写入字符个数,如果 <0 则写入出错。

4、read()
ssize_t read(int fd, const void *buf, size_t nbytes);
(1)fd:读出数据的文件对象

(2)buf:将数据读入到buf中。

(3)nbytes:指定要读取数据的大小,一般和buf大小的一致。

(4)返回值:如果 >0 则为读出字符个数,如果 <0 则读出出错。

5、close()
int close(int fd);
该函数用来关闭一个打开的文件描述符,关闭一个文件时还会释放该进程加在该文件上的所有记录锁。当一个进程终止时,内核将会自动关闭它所有打开的文件。

一、字符串拷贝

1、lseek()函数
off_t lseek(int fd, off_t offset, int whence);
通过lseek()这个函数我们可以调整文件偏移量的地址。因为在我们打开一个文件进行写入数据时,光标是跑到最后一个字符的后面的,如果这时候对文件的信息进行读取,那么它就会从光标处开始读取,这样光标后面是没有数据可读的,最后读取的数据为0,所以我们要进行文件偏移量设置。当然,对于未初始的buf,我们也应该使用memset()进行清空数组空间。
SEEK_SET 文件头
SEEK_CUR 当前位置
SEEK_END 文件尾

lseek(fd, 0, SEEK_SET); 将文件偏移量设置到了文件开始的第一个字节上;
lseek(fd, 0, SEEK_END); 将文件偏移量设置到文件最后一个字节上;
lseek(fd, -1, SEEK_END); 将文件偏移量设置到文件最后的倒数第一个字节上

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define BUFSIZE 1024
#define str "hello world\n"
int main(int argc, char * argv[])
{
	int	fd = -1;	
	int	rv = -1;
	char 	buf[BUFSIZE];
	fd = open("test.txt", O_RDWR | O_CREAT | O_TRUNC, 0666);
	if(fd < 0)
	{
		printf("open the file failure : %s ", strerror(errno));
		return -1;
	}
	printf("Open the file descriptor [%d] \n",fd);

	if((rv = write(fd, str, strlen(str))) < 0)
	{
		printf("write into the file failure : %s\n", strerror(errno));
		close(fd);
	}
	printf("Write %d bytes into the file \n", rv);

	rv = -1;
	memset(buf, 0, sizeof(buf));
	lseek(fd, 0, SEEK_SET);
	if((rv = read(fd, buf, sizeof(buf))) < 0)
	{
		printf("read the data from file failure: %s\n", strerror(errno));
		close(fd);
	}
	printf("read %d bytes data from file: %s\n", rv, buf);

	return 0;
}

运行效果:
在这里插入图片描述

二、文件拷贝
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define BUFSIZE 1024
int main(int argc, char *argv[])
{
	int	read_fd1 = -1, write_fd2 = -1;
	int	rv1 = -1, rv2 = -1;
	char	buf[BUFSIZE];
	read_fd1 = open(argv[1], O_RDONLY);
	write_fd2 = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0666);
	if( read_fd1 < 0 || write_fd2 < 0 )
	{
		printf("open the file1 failure : %s ", strerror(errno));
		return -1;
	}
	printf("Open the file descriptor [fd1 %s: %d] [fd2 %s: %d] \n", argv[1], read_fd1, argv[2], write_fd2 );
	memset(buf, 0, sizeof(buf));
	if((rv1 = read(read_fd1 , buf, sizeof(buf))) < 0)
	{
		printf("read the data from file failure: %s\n", strerror(errno));
		close(read_fd1);
		close(write_fd2);
		return -2;
	}
	if(rv2 = write(write_fd2 , buf, rv1) < 0)
	{
		printf("write the data failure: %s\n", strerror(errno));
		close(read_fd1);
		close(write_fd2);
		return -3;
	}
	printf("1\n");
	lseek(read_fd1 , 0, SEEK_SET);
	lseek(write_fd2 , 0, SEEK_SET);
	while((rv1 = read(read_fd1 , buf, sizeof(buf))) != 0)
	{	
		printf("2\n");
		write(write_fd2 , buf, rv1);
	}
	close(read_fd1);
	close(write_fd2);
	return 0;
}

运行效果:
在这里插入图片描述
三、总结
在读取数据的时候一定要注意文件偏移量,不然要么读取数据不全、要么读取不了数据,另外一个需要注意的就是,在每一次对文件操作完成之后,一定要关闭打开的文件描述符,因为假如工程量很大,需要不断地创建文件描述符在,这时候就导致溢出,fd最大可为1024个。有不足之处请各位大佬在评论区留言,谢谢。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

X 、case

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值