应用IO编程——文件IO

文件IO编程—非缓冲IO

2.1、概念

文件IO编程

通过使用系统调用中的函数接口对文件操作

标准IO通过文件指针操作文件,与标准IO不同的是,在文件IO中,操作文件是通过文件描述符。

文件描述符

是一个非负的正数,当打开一个现存文件或创建一个新文件时,内核向进程(程序)返回一个文件描述符

2.2、打开文件

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int flags);      //只是打开文件,文件不存在时,不会创建
int open(const char *pathname, int flags, mode_t mode);  //如果文件不存在,需要创建文件用
//参数1:pathname -----要打开的文件
//参数2:flags ------ 打开的方式:
	O_RDONLY:只读方式打开文件。
	O_WRONLY:可写方式打开文件。
	O_RDWR:读写方式打开文件
	O_CREAT:如果该文件不存在,就创建一个新的文件,并用第三的参数为其设 置权限。
	O_EXCL:如果使用O_CREAT时文件存在,则可返回错误消息。这一参数可测试文件是否存在。
	O_NOCTTY:使用本参数时,如文件为终端,那么终端不可以作为调用open()系统调用的那个进程的控制终端。
    O_TRUNC:如文件已经存在,那么打开文件时先删除文件中原有数据 ,类似于fopen中的"w"
	O_APPEND:以添加方式打开文件,所以对文件的写操作都在文件的末尾进行,,类似于fopen中的"a"
//参数3:mode  ------ 当第二个参数flags中包含:O_CREAT时,需要用到参数mode,mode表示创建文件的权限
//返回值:成功---返回最小的没有被使用的文件描述符,失败:-1
例如: 
int main(int argc,char **argv)
{

	int fd;

	//fd = open(argv[1],O_RDONLY|O_CREAT,0664); //以只读方式打开,如果不存在,则创建
	//fd = open(argv[1],O_WRONLY|O_CREAT,0664); //以只写方式打开,如果不存在,则创建
	//fd = open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0664); //以只写方式打开,如果不存在,则创建,如果存在,则清空,类似于fopen()的"w"
	fd = open(argv[1],O_WRONLY|O_CREAT|O_APPEND,0664); //以只写方式打开,如果不存在,则创建,如果存在,则追加,类似于fopen()的"a"
	if(fd < 0){
		perror("open");
		exit(1);
	}

	return 0;
}

2.3、关闭文件

#include <unistd.h>
int close(int fd);
//参数:fd ----文件描述符 
//返回值:成功---0,失败:-1

2.4、读数据

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);
//参数1:fd ----- 文件描述符
//参数2:buf ---- 内存空间的地址
//参数3:count ----内存空间的大小 
//返回值: 成功--返回读到的字节数,如果到文件末尾,返回0,失败--  -1

例如: 
int main(int argc,char **argv)
{
	char buf[SIZE];
	int ret;
	int fd;
#if 0
	while(1){
		bzero(buf,SIZE);
		ret = read(0,buf,SIZE);  //键盘输入时,也会接收换行符
		if(ret < 0){
			perror("read");
			exit(1);
		}
		printf("(%d):%s",ret,buf);
	}
#else
	//打开文件
	fd = open(argv[1],O_RDONLY);
	if(fd < 0){
		perror("open");
		exit(1);
	}

	//读取文件中的内容,并打印
	while(1){
		bzero(buf,SIZE);
		ret = read(fd,buf,SIZE);
		if(ret < 0){
			perror("read");
			exit(1);
		}else if(ret == 0){ //读到文件末尾
			close(fd);
			break;
		}else{
			printf("%s",buf);
		}
	}
#endif
	return 0;
}

2.5、写数据

ssize_t write(int fd, const void *buf, size_t count);
//参数1 ---- 文件描述符
//参数2 ---- 要写的数据的地址
//参数3 ---- 要写的数据的长度
//返回值: 成功--写入的数据的长度,失败--- -1

//注意:write在写数据时,有可能会写不够,所以需要分多次写入,通常会重写write函数,保证要写的数据全部被写进去
例如: 
#define SIZE 100

int my_write(int fd, char *buf,size_t count)
{
	int ret = 0,size = count;
	do{
		ret = write(fd,buf+ret,count);
		if(ret < 0){
			perror("write");
			return ret;
		}else{
			if(ret != count){
				count = count-ret;
				continue;
			}else
				break;
		}
	}while(1);
	return size;
}

int main(int argc,char **argv)
{
	char buf[SIZE];
	int ret;
	int fd;

	//打开文件
	fd = open(argv[1],O_WRONLY|O_CREAT,0664); //文件不存在则创建,文件存在,直接打开
	if(fd < 0){
		perror("open");
		exit(1);
	}
	//从键盘输入数据,并写入文件中
	while(1){
		bzero(buf,SIZE);
		printf("请输入数据:");
		fgets(buf,SIZE,stdin);
		buf[strlen(buf)-1] = '\0';  //去掉fgets获取的换行符

		if(!strncmp(buf,"quit",4))
			break;

		ret = my_write(fd,buf,strlen(buf));
		if(ret < 0){
			perror("my_write");
			exit(1);
		}
	}
	return 0;
}

//练习:用文件IO相关函数实现文件拷贝

2.6、设置文件位移量

#include <sys/types.h>
#include <unistd.h>

off_t lseek(int fd, off_t offset, int whence);
//参数1 ------ 文件描述符 
//参数2 ------ 要设置的文件位移量
//参数3 ------ 文件位移量偏移的基点:
				SEEK_SET   ----从文件起始位置偏移offset
				SEEK_CUR   ----从当前位置偏移offset
				SEEK_END   ----从文件末尾偏移offset

//使用lseek函数创建空洞文件
//空洞文件----空内容为空的文件,但是占用了一定的磁盘大小
//如何创建空洞文件,例如: 
int main(int argc,char **argv)
{
	char buf[SIZE] = "end";
	int fd;

	//1,打开文件
	fd = open(argv[1],O_WRONLY|O_CREAT,0664); //不能以追加方式打开文件
	if(fd < 0){
		perror("open");
		exit(1);
	}

	//2,修改文件当前的位移量
	lseek(fd,1024,SEEK_SET);

	//3,写入一个结束标志数据
	write(fd,buf,strlen(buf));

	return 0;
}

2.7、dup和dup2的用法

2.7.1、赋值文件描述符

int dup(int oldfd);
//参数:oldfd  ------被复制的文件描述符
//返回值;成功--新的没有被使用的最小的文件描述符,它是oldfd的一个拷贝,失败--- -1 

//接续写
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define SIZE 100

int main(int argc,char **argv)
{
    char buf[SIZE] = "hello world";
    int fd,newfd;


#if 1
    write(STDOUT_FILENO,buf,strlen(buf));

    fd = dup(STDOUT_FILENO);  //复制文件描述符STDOUT_FILENO,得到一个新的文件描述符fd

    write(fd,"farsight",8);
#else
    //1,打开文件
    fd = open(argv[1],O_WRONLY|O_CREAT,0664); //文件不存在则创建,文件存在,直接打开
    if(fd < 0){
		perror("open");
		exit(1);
    }

    write(fd,buf,strlen(buf));

    newfd = dup(fd);  //复制fd中保存的文件描述符,返回新的文件描述符保存到newfd中

    write(newfd,"farsight",8);

#endif
    return 0;
}

//运行结果:
(第一部分是屏幕上打印)
hello worldfarsightesdon@ubuntu:/mnt/hgfs/tolinux$
(第二部分是输出到一个文件,文件内容为)
hello worldfarsight  

2.7.2、文件描述符重定向

int dup2(int oldfd, int newfd);
//参数1 ----- 目标:文件描述符
//参数2 -----  被重定向的文件描述符
//将newfd中的文件描述符重定向到oldfd保存的文件描述符,同时关闭newfd中原来的文件描述符对应的文件
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define SIZE 100

int main(int argc,char **argv)
{
    char buf[SIZE] = "helloworld";
    int fd,newfd;


    fd = open(argv[1],O_WRONLY|O_CREAT,0664);
    if(fd < 0){
		perror("open");
		exit(1);
    }
#if 0
    newfd = dup(STDOUT_FILENO);//让newfd也指向标准输出
    dup2(fd,STDOUT_FILENO);//让标准输出指向fd。

    write(STDOUT_FILENO,buf,strlen(buf));
    printf("farsight\n");
    fflush(stdout);

    dup2(newfd,STDOUT_FILENO);//让标准输出重新指向标准输出
    printf("welcome to farsight\n");
#else
    write(fd,buf,strlen(buf));

    newfd = dup(fd);

    write(nwfd,"far",3);
#endif
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值