前言

学完 Linux 文件I/O 系统调用,今天来做一下在 Linux 下使用C语言实现文件拷贝。

一、实现过程

本次实现的效果是像 cp 命令一样,cp 源文件 目标文件,把源文件拷贝到目标文件中去。

1、判断源文件是否存在

  • ①、文件拷贝,顾名思义就是将一个文件内容完完全全的复制到另一个文件中去
    那么首当其冲的就是源文件要存在
  • ②、使用 access() 函数来确定文件的访问权限,作为源文件,我们首先要确认该文件存不存在
//判断源文件是否存在
if(access(argv[1], F_OK) < 0)
{
	printf("Source File '%s' not exist\n", argv[1]);
	return -1;
}
printf("Source File '%s' is exist\n", argv[1]);

2、判断源文件是否可读

  • ①、判断源文件是否可读
//判断文件是否可读
if (access(argv[1], R_OK) < 0)
{
	printf("Source File '%s' UnReadable\n", argv[1]);
	return -2;
}
printf("Source File '%s' can be Read\n", argv[1]);

3、打开源文件

  • ①、以只读的方式打开源文件
//打开源文件
	if ((fd1 = open(argv[1], O_RDONLY)) < 0)
	{
		printf("Open Source File '%s' failure: %s", argv[1], strerror(errno));
		return -3;
	}
	printf("Open Source File '%s' fd[%d] successfully\n", argv[1], fd1);

4、打开目标文件

  • ①、以读写的方式打开目标文件
    若目标文件不存在,则创建目标文件
    若目标文件已存在,则将目标文件的长度的截取为0【清空内容】
//打开目标文件
if ((fd2 = open(argv[2], O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
{
	printf("Open/Create Destination File '%s' failure: %s\n", argv[2], strerror(errno));
	goto cleanup;
}
printf("Open/Create Destination File '%s' fd[%d] successfully\n", argv[2], fd2);

5、从源文件中读数据,写到目标文件

  • ①、从源文件中一次读1024字节的数据,读完一次数据,就写一次数据到目标文件中,具体操作如下。
  • ②、从源文件中读取 sizeof(buf) 字节大小的内容存到 buf 中,这里是一次性读1024个字节的数据
    若 rv1 不为0,则代表有数据
    若 rv1 为0,则代表数据已读完
  • ②、把 buf 中 rv1 字节大小(即从源文件中读到的数据长度)的数据,写入到目标文件中。
  • ③、count 用于计数,写完一次后,count++,可观察共读写了多少次。
//从源文件中读数据到buf,再将buf的数据写到目标文件中
while ((rv1 = read(fd1, buf, sizeof(buf))) != 0)
{
	if ((rv2 = write(fd2, buf, rv1)) < 0)
	{
		printf("Count[%d] Write failure\n", count);
	}
	count++;
}

二、具体代码

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

#define BUF_LEN 1024

int main(int argc, char **argv)
{
	int rv1 = -1;
	int rv2 = -1;
	int fd1 = -1;
	int fd2 = -1;
	char buf[BUF_LEN];
	int count = 0;

	//判断源文件是否存在
	if (access(argv[1], F_OK) < 0)
	{
		printf("Source File '%s' not exist\n", argv[1]);
		return -1;
	}
	printf("Source File '%s' is exist\n", argv[1]);

	//判断文件是否可读
	if (access(argv[1], R_OK) < 0)
	{
		printf("Source File '%s' UnReadable\n", argv[1]);
		return -2;
	}
	printf("Source File '%s' can be Read\n", argv[1]);

	//打开源文件
	if ((fd1 = open(argv[1], O_RDONLY)) < 0)
	{
		printf("Open Source File '%s' failure: %s", argv[1], strerror(errno));
		return -3;
	}
	printf("Open Source File '%s' fd[%d] successfully\n", argv[1], fd1);
	
	//打开目标文件
	if ((fd2 = open(argv[2], O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
	{
		printf("Open/Create Destination File '%s' failure: %s\n", argv[2], strerror(errno));
		goto cleanup;
	}
	printf("Open/Create Destination File '%s' fd[%d] successfully\n", argv[2], fd2);
	
	//从源文件中读数据到buf,再将buf的数据写到目标文件中
	while ((rv1 = read(fd1, buf, sizeof(buf))) != 0)
	{
		if ((rv2 = write(fd2, buf, rv1)) < 0)
		{
			printf("Count[%d] Write failure\n", count);
		}
		count++;
	}

	printf("The File has been copied and Executed %d times\n", count);

	
cleanup:
	if (fd1 > 0)
		close(fd1);
	if (fd2 > 0)
		close(fd2);

	return 0;
}

三、运行效果

在这里插入图片描述
这里的源文件 ld.so.cache 是为了测试大文件是否也能正常拷贝,从 /etc/ 目录下拐来的
从上图的运行效果上来看,ld.so.cache 有46287字节的数据
经过验证,一次拷贝1024字节,46287 = 1024 * 45 + 207,所以总共拷贝了46次,没有出现数据遗漏的情况。

测试一个不存在的文件
在这里插入图片描述

现在将 ld.so.cache 文件的权限设置为不可读,虽然文件存在,但是没有可读的访问权限,该文件不可读,会直接退出程序,并说明错误原因
在这里插入图片描述


总结

以上是对Linux 文件I/O 系统调用的一些理解,如有写的不好的地方,还请各位大佬不吝赐教

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐