基础IO—01

基础IO—01

1.标准库的IO接口

标准库的IO接口有:fopen/fwrite/fread/fseek/fclose

FILE* fopen(char* filename, char* mode);//(文件名称,打开方式)

打开方式:r只读/r+读写/w只写/w+只读/a追加写/a+追加读写/b二进制操作

r+和w+的区别:r+读写打开文件,若文件不存在则报错/w+读写打开文件,若不存在文件则创建,若存在则清空原有文件内容。

b默认清空文件内容。如果不指定b则认为文件是文本操作,加上b则认为是二进制操作。

a不仅仅是追加写,如果文件不存在还会创建新文件。

返回值:成功返回一个FILE*的文件流指针,失败则返回NULL。

size_t fread(char* buf, size_t block_size, size_t block_count, FILE* fp);
//(缓冲区,块大小,快个数,文件流指针)
size_t fwrite(char* data, size_t block_size, size_t block_count, FILE* fp);
//(数据首地址,块大小,快个数,文件流指针)

fread/fwrite操作的数据实际大小为块大小*块个数。

返回值:返回实际操作的块个数。

fread/fwrite推荐块大小为1,快个数是想要操作的数据长度。

int fseek(FILE* fp, long offset, int whence);//将文件从whence位置偏移offset个字节
int fclose(FILE* fp);//关闭文件流指针,释放资源

fseek:文件没有数据也可以跳转读写位置。

#include<stdio.h>
#include<string.h>
int main()
{
	FILE* fp = fopen("./test.txt", "r+");
	//fseek(fp, 0, SEEK_SET);
	fseek(fp, 0, SEEK_END);
	char* ptr = "hello siwei\n";
	int ret = fwrite(ptr, strlen(ptr), 1, fp);
	printf("%d\n",ret);
	fseek(fp, 0, SEEK_SET);
	char buf[1024] = {0};
	ret = fread(buf, 1, 1023, fp);
	printf("%d\n",ret);
	printf("%s\n", buf);
	fclose(fp);
	return 0;
}
2.系统调用IO接口

系统调用的IO接口有:open/read/write/lseek/colse

int open(char* filename, int flag, mode_t mode);

filename:想要打开的文件名称。

flag:选项参数–文件的打开方式。有必选项和可选项两种。

必选项:O_RDONLY-只读 O_WRONLY-只写 O_RDWR-读写

可选项:O_CREAT-文件存在则打开,不存在则创建。O_EXCL与O_CREAT同时使用,文件存在则报错,不存在则创建。O_TRUNC-打开文件的同时清空原有内容。O_APPEND-追加写。

mode:权限–如果使用了O_CREAT有可能创建新文件,就一定要指定文件权限,八进制数字形式。

返回值:成功返回一个非负整数—文件描述符—文件操作句柄;失败返回-1。

size_t write(int fd, char* data, size_t count);

fd:open返回的文件描述符—文件操作句柄。

data:要写入文件的数据的空间首地址。

count:要写入的数据大小。

返回值:成功返回实际写入文件的数据字节长度;失败返回-1。

size_t read(int fd, char* buf, size_t len);

fd:open返回的文件描述符—文件操作句柄。

buf:从文件中读取数据放到那块缓冲区的首地址。

len:想要读取的长度,len的长度不能大于缓冲区的大小。

返回值:成功返回的是实际读取到的数据字节长度;失败返回-1。

size_t lseek(int fd, long offset, int whence);

fd:open返回的文件描述符—文件操作句柄。

offset:偏移量。

whence:从哪里开始偏移。SEEK_SET-文件起始位置,SEEK_CUR-文件当前读写位置,SEEK_END-文件末尾。

返回值:成功返回当前位置对于起始位置的偏移量;失败返回-1。

int close(int fd);

通过文件描述符关闭文件,释放资源。

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
int main()
{
	int fd = open("./test.txt", O_RDWR|O_CREAT, 0777);
	lseek(fd, 0, SEEK_END);
	char* ptr = "hello world\n";
	int ret = write(fd, ptr, strlen(ptr));
	printf("ret = %d\n", ret);
	lseek(fd, 0, SEEK_SET);
	char buf[1024] = {0};
	ret = read(fd, buf, 1024);
	printf("ret = %d\n%s\n", ret, buf);
	close(fd);
	return 0;
}
3.文件描述符

文件描述符起始就是内核中一个进程打开的文件描述信息表的下标,通过这个下标可以在内核中找到相应的文件描述信息,通过这个描述信息可以实现文件的操作。

如果打开了一个文件,对于这个文件操作完成后一定要关闭,释放资源。因为文件描述符实际是有限的,若不关闭文件,文件描述符用光,则在进程中就打不开新文件了。

一个程序运行起来在进程中会默认打开三个文件:标准输入-0-stdin/标准输出-1-stdout/标准错误-2-stderr。

文件描述符的分配规则:最小未使用规则。分配文件描述信息表中,文件描述符最小且没有使用的。

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
int main()
{
	close(1);
	umask(0);
	int fd = open("./test.txt", O_RDWR|O_CREAT, 0664);
	printf("fd = %d\n", fd);
	fflush(stdout);
	close(fd);
}

printf打印数据到标准输出中,如果关闭了标准输出1,打开新的文件后,按照文件描述符的分配规则。这个新打开的文件描述符就是1,所以在这个程序中printf并没有将数据打印出来,而是在刷新缓冲区之后,将数据写入到了文件中。

4.重定向

重定向:将数据不再写入原本的文件,而是写入新的指定的文件中—实现方式就是替换这个描述符对应的文件描述信息,实际上是描述符的重定向,改变描述符所指向的文件,就改变了数据的流向。>清空重定向,>>追加重定向。

int dup2(int oldfd, int newfd);//描述符重定向函数

让newfd这个描述符也指向oldfd所指向的文件,这时候oldfd和newfd都能够操作oldfd所指向的文件。

在minishell中实现>/>>标准输出重定向:

#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
int main()
{
	umask(0);
	while(1)
	{
		printf("[sw@minishell]$ ");
		fflush(stdout);//刷新标准输出缓冲区i
		char buf[1024] = {0};
		fgets(buf, 1023, stdin);
		buf[strlen(buf) - 1] = '\0';
		char* ptr = buf;
		int flag = 0;
		char* file = NULL;
		while(*ptr != '\0')
		{
			if(*ptr == '>')
			{
				flag = 1;
				*ptr = '\0';
				ptr++;
				if(*ptr == '>')
				{
					flag = 2;
					ptr++;
				}
				while(*ptr == ' ' && *ptr != '\0')ptr++;
				file = ptr;
				while(*ptr != ' ' && *ptr != '\0')ptr++;
				*ptr = '\0';
			}
			ptr++;
		}	
		char* argv[32] = {NULL};
		int argc = 0;
		ptr = buf;
		while(*ptr != '\0')
		{
			if(*ptr != ' ')
			{
				argv[argc] = ptr;
				argc++;
				while(*ptr !=' ' && *ptr != '\0')
				{
					ptr++;
				}
				*ptr = '\0';
			}
			ptr++;
		}
		argv[argc] = NULL;
		pid_t pid = fork();
		if(pid == 0)
		{
			if(flag == 1)
			{
				int fd = open(file, O_WRONLY|O_CREAT|O_TRUNC, 0777);
				dup2(fd, 1);
			}
			else if(flag == 2)
			{
				int fd = open(file, O_WRONLY|O_CREAT|O_APPEND, 0777)dup2(fd, 1);
			}
			execvp(argv[0], argv);
			exit(0);
		}
		wait(NULL);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值