【Linux--lv4--Day3】文件I/O-基本介绍、打开/关闭文件、读/写数据、定位

Day3

文件I/O
基本介绍、与标准I/O的区别
标准I/O文件I/O
遵循ANSI C标准遵循POSIX(可移植操作系统接口)标准定义的一组用于文件访问的函数
缓冲机制(减少系统调用的次数,从而提高效率)没有缓冲机制,每次读写都会引起系统调用
通过FILE结构体(也就是 )来描述打开文件的相关信息通过 文件描述符 来表示一个打开的文件
一般来说,只用来访问最基本的文件类型使用更加广泛,可以访问各种类型文件

特别说明:文件描述符(文件I/O的核心概念)

  • 每个打开的文件都对应一个文件描述符
  • 文件描述符是一个非负正数,Linux为程序中每个打开的文件分配一个文件描述符
  • 文件描述符从0开始分配,依次递增,每次分配都是从最小,可用的文件描述符开始分配
  • 文件I/O操作通过文件描述符来完成
  • 0 指代标准输入流,1 指代标准输出流, 2则是标准错误流
创建或打开一个文件

文件I/O中使用open函数来创建或者打开一个文件
头文件:#include <fcntl.h>
int open(const char *path, int oflag,...);

  • 函数为int型,成功时返回打开文件的文件描述符,出错时返回EOF
  • 打开一个已经存在的文件时,只需要使用前两个参数
  • 用来创建一个文件时,需要用到三个参数,第三个参数用来指明所创建的新文件的权限
  • 对于设备文件只能打开,不能创建

注意:参数列表说明

原型int open(const char * pathname, int flags, mode_t mode)
pathname被打开的文件名,可以是绝对路径
flagsO_RDONLY:只读方式打开文件
O_WDONLY:只写方式打开文件
O_RDWD:读写方式打开文件 (以上三种参数互斥)
O_CREAT:如果文件不存在,就创建一个新文件,并且指定第3个参数为新文件设置权限
O_EXCL:如果使用O_CREAT,但文件已经存在,则可以返回错误信息,这一参数常用来测试此文件是否已经存在
O_TRUNC:如果文件已经存在,那么打开文件时先删除文件中的原有数据(先清空)
O_APPEND:以添加方式添加文件,所以对文件的写操作都在文件的末尾进行
O_NOCTTY:使用本参数时,如果文件为终端,那么终端可以作为调用open() 系统调用的那个进程的控制终端(很少用到)
mode被打开的文件的存取权限,为8进制表示法

例1:以只写方式打开文件 1.txt ,如果文件不存在则创建,如果文件存在则清空

#include <stdio.h>
#include <fcntl.h>
#include <errno.h>

int main(int argc,char * argv[])
{
        int fd;
        if((fd=open("1.txt",O_WRONLY|O_CREAT|O_TRUNC,0666))<0)
        {
         perror("open");
         return -1;
        }
        return 0;
}

效果如下:

linux@linux-virtual-machine:~/test/lv4/Day3$ ./open
linux@linux-virtual-machine:~/test/lv4/Day3$ ls -l
total 16
-rw-r--r-- 1 linux linux    0 510 17:12 1.txt(新建了1.txt,并且大小为0-rwxr-xr-x 1 linux linux 8344 510 17:11 open
-rw-r--r-- 1 linux linux  208 510 17:10 open.c

例2:以读写方式打开文件1.txt,如果文件不存在则创建,如果文件存在则报错

#include <stdio.h>
#include <fcntl.h>
#include <errno.h>

int main(int argc,char * argv[])
{
     int fd;
     if((fd=open("1.txt",O_RDWR|O_CREAT|O_EXCL,0666))<0)
     {
        if(errno==EEXIST)
                perror("exist error!");
        else
                perror("other error!");
     }
     return 0;
}

效果如下:

linux@linux-virtual-machine:~/test/lv4/Day3$ vi error.c
linux@linux-virtual-machine:~/test/lv4/Day3$ gcc error.c -o error
linux@linux-virtual-machine:~/test/lv4/Day3$ ./error
exist error!: File exists

从结果可以看出O_EXCL常用来判断创建一个已存在的文件所产生的错误,当我们用O_CREAT创建一个已经存在的文件时反而会出错。

文件的关闭

close函数用来关闭一个打开的文件
#include <unistd.h
int close(int fd)这里的 fd 就是要关闭的文件的文件描述符

  • 成功时返回0,出错时返回EOF
  • 程序结束时,会自动关闭所有打开的文件
  • 文件关闭时,描述它的文件描述符就不再代表此文件
从文件中读取数据

read函数
#include <unistd.h>
ssize_t read(int fd,void * buf,size_t count);

  • buf为接受数据的缓冲区的首地址,需要提前创建好。
  • count不应该超过buf的大小,一般就把count设为缓冲区的大小,以免发生溢出的问题。
  • 成功时返回的是实际读取的字节数,出错时返回EOF
  • 读到文件末尾时返回0

例3:从指定的文本文件"1.txt" 读取内容,并统计其大小

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

int main(int argc,char * argv[])
{
        int fd;
        int n,total=0;
        char buf[64];

        if(argc<2)
        {
         printf("Usage: %s <file>\n",argv[0]);
         return -1;
        }
        if((fd=open("1.txt",O_RDONLY))<0)
        {
                perror("open");
                return -1;
        }
        while((n=read(fd,buf,64))>0)
        {
          total=total+n;
        }
        printf("The %s has %d bytes\n",argv[1],total);
        return 0;
}

效果如下

linux@linux-virtual-machine:~/test/lv4/Day3$ vi 1.txt
linux@linux-virtual-machine:~/test/lv4/Day3$ cat -s 1.txt
123456789
linux@linux-virtual-machine:~/test/lv4/Day3$ ./read 1.txt
The 1.txt has 10 bytes
向文件中写入数据

write函数
#include <unistd.h>
ssize_t write(int fd, void * buf,size_t count)

  • 成功时返回实际写入的字节数,出错时返回EOF
  • buf是发送数据的缓冲区
  • count不应超过缓冲区buf的大小

例4:将键盘输入的内容直接写入文件"4.txt",手动输入此文件名,如果不存在就创建,如果存在先清空,再存放数据,直到输入quit

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

int main(int argc,char * argv[])
{
        char buf[64];
        int fd;
        if((fd=open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0666))<0)
        {
                perror("open");
                return -1;
        }
        while(fgets(buf,64,stdin)!=NULL) //1. 先将键盘输入的数据放入缓冲区buf
        {
                if(strcmp(buf,"quit\n")==0)//这里注意 fgets()会把换行符也读进去,因此这里相比较的字符串一定要加\n
                        break;
                write(fd,buf,strlen(buf));//2. 再将缓冲区的数据存入文件中
        }
        return 0;
}

效果如下

linux@linux-virtual-machine:~/test/lv4/Day3$ vi write.c
linux@linux-virtual-machine:~/test/lv4/Day3$ gcc write.c -o write
linux@linux-virtual-machine:~/test/lv4/Day3$ ./write 4.txt
123456    
qwer
rty
quit
linux@linux-virtual-machine:~/test/lv4/Day3$ cat -s 4.txt
123456
qwer
rty

例5:利用文件I/O完成文件的复制,文件名通过命令行参数确定。

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

int main(int argc,char * argv[])
{
        int fds,fdd;
        int n;
        char buf[64];
        if(argc<3)
        {
        printf("Usage:%s <source_file> <dst_file>\n",argv[0]);
        return -1;
        }
        if((fds=open(argv[1],O_RDONLY))==-1)
        {
                perror("open");
                return -1;
        }
        if((fdd=open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0666))<0)
        {
                fprintf(stderr,"open %s:%s\n",argv[2],strerror(errno));
                return -1;
        }
        while((n=read(fds,buf,64))>0)
        {
                write(fdd,buf,n);
        }
        close(fds);
        close(fdd);

        return 0;
}

效果如下:

linux@linux-virtual-machine:~/test/lv4/Day3$ gcc cp.c -o cp
linux@linux-virtual-machine:~/test/lv4/Day3$ ./cp 4.txt 5.txt(此时目录中没有5.txt这个文件)
linux@linux-virtual-machine:~/test/lv4/Day3$ cat -s 5.txt(显示5.txt被创建,而且内容与4.txt相同)
123456
qwer
rty
linux@linux-virtual-machine:~/test/lv4/Day3$ ./cp 1.txt 5.txt(此时原本5.txt的内容被清空,又放入新的内容)
linux@linux-virtual-machine:~/test/lv4/Day3$ cat -s 1.txt
123456789
linux@linux-virtual-machine:~/test/lv4/Day3$ cat -s 5.txt
123456789
定位文件

lseek函数
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);

  • 成功时返回当前文件的读写位置;出错时返回EOF
  • 参数 offset 和参数 whence 同 fseek 一样。(SEEK_SET | SEEK_CUR | SEEK_END)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值