Linux下文件读写的操作

2020-03-16   63 次阅读


摘要:Linux系统管理与开发课程中对于文件的读写操作的认识并且运用C语言进行模拟读、写和复制操作。

文件开关以及读写说明

读操作read()

read(int fd, void *buf, size_t count);

len: 请求读取的字节数

返回值:

​ -1 :读取失败

​ 0:没有读取到数据

​ n:读取到的字节数(n:1~len)

实际情况下:

​ < 0 : 失败

​ = len: 正常读取

​ = 0~len-1: 读取完毕

写操作write()

write(int fd, const void *buf, size_t count);

返回值:

​ -1 :读取失败

​ n:写入字符个数(n:1~len)

打开文件open()/creat()

creat(文件名称,权限模式); = open(文件名称,O_CREAT,权限模式);

类型:

O_RDONLYO_WRONLYO_RDWRO_APPENDO_CREATO_TRUNC
只读只写读写末尾追加若文件存在,此标志无用;若不存在,建新文件若文件存在,则长度被截为0,属性不变

权限模式:

S_I <权限><对象>

​ 权限:R, W, X, RWX

​ 对象:USR, GRP, OTH, U, G, O

​ 举个栗子:

usr:rwx;	group:rw;	other:r;
creat("test", S_IRWXU | S_IRGRP |S_IROTH);
=
open("test",O_CREAT, S_IRWXU | S_IRGRP |S_IROTH)

tips:

权限位:3个八进制数

764

creat("test",010764);

关闭文件close()

close(句柄);

读操作

解释一下int main(int argc, char** argv)的意思:

例如一条指令:cp abc.txt xyz.log

argc = 3 (指令的三个部分) argv[0] = cp argv[1]=abc.txt argv[2]= xyz.log

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#define LEN 512
int bail(const char* str){
	printf("Error(%d):",errno);
	perror(str);
	exit(-1);
}

int main(int argc, char** argv){
	int fd = -1;
	char buf[LEN] = {0};
	int read_return = -1;
	fd = open(argv[1],O_RDONLY);
	if(fd < 0)
		bail("open file error.");
	printf("fd = %d \n",fd);
	
	read_return = read(fd, buf, sizeof(buf));
	while(read_return > 0)
	{
		printf("%s",buf);
		memset(buf, 0, sizeof(buf));
		read_return = read(fd, buf, sizeof(buf));
	}
	if (read_return < 0){
		close(fd);
		bail("read file error.");
	}

	close(fd);
	return 0;
}

 

写操作

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#define LEN 512
int bail(const char* str)
{
	printf("Error(%d):",errno);
	perror(str);
	exit(-1);
}

int main(int argc, char** argv)
{
	int fd = -1;
	char buf[LEN] = {0};
	int write_return = -1;
	int read_return = -1;
	//fd = open(argv[1],O_WRONLY);   //以只写的方式写入
	//fd = open(argv[1],O_WRONLY | O_APPEND);	//以只写+尾部追加的方式写入
	fd = open(argv[1],O_CREAT | O_WRONLY | O_APPEND, S_IRUSR | S_IRGRP | S_IROTH);
	if(fd < 0) 
		bail("open file error.");
	printf("fd = %d \n",fd);
	printf(">");
	gets(buf);
	while(strcmp(buf, "quit") != 0)
	{
		write_return = write(fd, buf, strlen(buf));
		if(write_return <0)
		{
		close(fd);
		bail("Write file error.");
		}
		memset(buf , 0, sizeof(buf));
		printf(">");
		gets(buf);
	}
	

	close(fd);
	return 0;
}

 

复制功能的实现

  1. 打开源文件
  2. 创建目标文件
  3. 读取源文件
  4. 写入目标文件
  5. 关闭句柄退出
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#define LEN 512
int bail(const char* str)
{
	printf("Error(%d):",errno);
	perror(str);
	exit(-1);
}

int main(int argc, char** argv)
{
	int read_fd = -1;
	int write_fd = -1;
	char buf[LEN] = {0};
	int write_return = -1;
	int read_return = -1;

	read_fd = open(argv[1],O_RDONLY);
	write_fd = open(argv[2],O_CREAT | O_RDWR , 010755);
	if(read_fd < 0) 
		bail("open file error.");
	if(write_fd < 0)
	{
		close(read_fd);
		bail("Create file error.");
	}
	
	read_return = read(read_fd, buf, sizeof(buf));
	while( read_return > 0)
	{
		write_return = write(write_fd, buf , read_return);
		if(write_return < read_return)
		{
			close(read_fd);
			close(write_fd);
			bail("Write file error.");
		}
		memset(buf, 0, sizeof(buf));
		read_return = read(read_fd, buf, sizeof(buf));
	}
	
	if(read_fd < 0)
	{
		close(read_fd);
		close(write_fd);
		bail("Read file error.");
	}
	
	close(read_fd);
	close(write_fd);
	return 0;
}

 

tips:

复制操作中关于文件权限判断和使用的问题未能成功实现,留待下次更新。

---3.18更新---

访问文件(判断权限)

access函数使用方法:

access("文件名称",测试权限)

测试权限:

​ R_OK:读可以

​ W_OK:写可以

​ X_OK:执行可以

​ F_OK:文件存在

返回值:

​ 0:测试成功

​ -1:测试失败

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

int bail(const char* str){
	printf("Error(%d):",errno);
	perror(str);
	exit(-1);
}

int main(int argc, char** argv)
{
	int ret = -1;
	ret = access(argv[1],F_OK);
    //ret = access(argv[1],F_OK | X_OK);     //同时检测满足文件是否同时存在和可执行
	if (ret < 0)
		printf("File not exist.\n");
	else
		printf("File exist.\n");
	close(ret);
	return 0;
}

这就很好的解释了在读写前可以使用access函数判断权限。

读操作:

ret = access(argv[1],F_OK | R_OK);

if (ret ==0)

	fd = open();

写操作:

ret = access(argv[1],F_OK );

if(ret <0)

	fd = creat();

else

	printf("overwrite?");

获取状态信息

stat函数:

struct stat st;

stat(“文件名”,&st);

返回值:

​ -1:失败

st返回值:

​ st.st_size:文件大小

​ st.st_mode:文件类型、权限

​ st.st_xtim:时间相关参数(秒为单位,用ctime转换)

​ st.mode:

​ ①st.mode&S_IFMT

​ ②宏函数:S_ISDIR、S_ISREG、S_ISLNK、S_ISFIFO、S_ISCHR、S_ISSOCK

获取文件信息

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

int bail(const char* str){
	printf("Error(%d):",errno);
	perror(str);
	exit(-1);
}

int main(int argc, char** argv)
{
	int ret = -1;
	struct stat bs;
	
	memset(&bs,0,sizeof(bs));
	ret = stat(argv[1],&bs);
	if (ret < 0)
		bail("Stat error.\n");
	
	if (S_ISDIR(bs.st_mode))
		printf(" %s \t","D");
	else if (S_ISREG(bs.st_mode))
		printf(" %s \t","-");
	else if (S_ISLNK(bs.st_mode))
		printf(" %s \t","l");
	else
		printf(" %s \t","u");
	printf("%lld\t",bs.st_size);
	printf("%o\t",bs.st_mode);
	printf("%s\t",ctime(&bs.st_atime));
	
	return 0;
}

一下为运行截图

image-20200318144324692

获取权限信息并复制到另一文件

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

int bail(const char* str){
	printf("Error(%d):",errno);
	perror(str);
	exit(-1);
}

int main(int argc, char** argv)
{
	int ret = -1;
	int dfd = -1;
	struct stat bs;
	memset(&bs , 0, sizeof(bs));
	ret = stat(argv[1],&bs);
	dfd = creat(argv[2],bs.st_mode);
	
	return 0;
}

如下图所示

image-20200318144820783

本文由 hongCYu 创作,如果您觉得本文不错,请随意赞赏
采用 知识共享署名4.0 国际许可协议进行许可
原文链接:https://hongcyu.cn/posts/linux-rw.html
最后更新于:2020-12-03 15:45:07

Coffee