13.Linux 文件IO编程

面向过程

*把问题分解为一系列的步骤

*在函数里面一步一步实现这些步骤

*根据实际 需求调用函数

面向对象

*把构成问题的事物分解成一个一个的对象

*调用对象里面的方法属性解决问题

*面向对象有助于维护和扩展代码

面向对象三大特性

*封装性:隐藏封装内部的一些细节

*继承:复用现有的代码

*


                                                一切皆文件        

Linux内核

屏蔽硬件区别,把所有的硬件设备抽象成文件,提供统一的接口给用户使用

虚拟文件系统:

抽象层、对文件的访问实际上是对抽象层的访问。

抽象对象:封装了底层读写细节,使用C语言的多态来实现具体文件系统的接口

普通文件系统:

-ext4

-fat32

-ubifs

特殊文件系统:

-进程文件系统:procfs,挂载在/proc,存放进程相关信息,任务管理器。

-设备文件系统:devfs,挂载在/dev。存放硬件操作相关的接口。


                                                文件描述符和打开模式

系统IO编程

*open

*write

*read

*iseek

*close

伪代码:

int fd;

fd=open(filename,flags,mode);

iseek(fd,offset,whence);

write(fd,buf,write_len);

read(fd,buf,read_len);

close(fd);

文件描述符

特殊的索引

实际上就是进程中file_struct结构体成员fd_array的数组下标

文件的打开模式

主模式:

*O_RDONLY:只读模式

*O_WRONLY:只写模式

*O_RDWR:读写模式

副模式:

O_CREATE:当文件不存在,需要去创建文件

O_APPEND:追加模式(把这个文件的读写位置设置到文件的尾巴

O_DIRECT:直接IO模式(write函数和read函数里面读取的数据不需要通过页缓存区

O_SYNC:同步模式(所有数据都会从页缓存区写到磁盘里面去

O_NOBLOCK:非阻塞模式()

进程

每个程序本质上就是一个进程

标准IO编程


                                                open_close函数

OPEN函数

头文件:
#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,int perms)

①pathname

②flags:文件的打开模式

主模式:1.O_RDONLY:只读模式            2 .O_WRONLY:只写模式               3.O_RDWR:读写模式

副模式:1.O_CREATE:当文件不存在,需要去创建文件(剩下的用到再说吧)

O_APPEND:追加模式

O_DIRECT:直接IO模式

O_SYNC:同步模式

O_NOBLOCK:非阻塞模式

perms:指定文件权限如0777,0666.

int fd = open("file",O_RDWR|O_CREAT,0666);

返回值

成功:文件描述符

失败:-1

CLOSE函数

头文件:
#include <unistd.h>

函数原型:
int close(int fd)

返回值:

成功:0

失败:-1


lseek函数

 使用lseek函数之前先要包含头文件#include <unistd.h>

 函数原型
ssize_t read(int fd,void *buff,size_t count)

需要三个参数

{

        1.int fd:用open文件返回来的文件描述符

        2.void *buff:读取文件后所需要填充到的buff地址

        3.size_t count:返回值

成功:

①返回值为count:成功读取全部字节
②0~count:
 剩余文件长度小于count
 读取期间被异步信号打断

③失败:

-1,读取错误


 write函数

使用write函数之前需要包含头文件同read函数的头文件一样#include <unistd.h>

 函数原型(跟read函数很像)
ssize_t write(int fd,void *buff,size_t count)

{

①int fd:用open文件返回来的函数描述符

②void *buff:写入内容的buff地址,例如(“123”)

③size_t count:返回值  (字节数)

如果成功:①count:成功写入全部字节
                  ② 0~count(大于0小于count): 写入期间被异步信号打断

如果失败: -1,读取错误

}

实现复制普通文件功能的小实验

#include <unistd.h>       //使用到read、write函数把头文件包含进来
#include <sys/types.h>    //用到open函数把头文件包含进来
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>         //因为后续会用到printf函数打印

int main(int argc,char** argv)     //main函数需要接收从控制台传来的参数
{
        int fd1,fd2;                //定义两个open文件描述符
        char buf[512];              //定义一个512字节的缓冲区
        int read_size;              //read_size用来表示读取的字节数量

        if(agrc != 3)               //判断如果main函数接收到的参数数量不等于3的话,让它报错     
        {
                printf("param error!\r\n");    
                return -1;           
        }

        fd1 = open(argv[1],O_RDONLY);//打开要复制的文件,参数名保存在main函数的第一个参数里,打开模式为只读模式,把返回的文件描述符赋值给fd1的变量
        fd2 = open(agrv[2],O_WRONLY|O_CREAT,0666); //用open函数去创建一个新的文件且模式为只写模式,O_CREAT的副模式,也就是说当我们这个文件不存在的时候,创建一个新文件,最后指定文件权限

        if(fd1 < 0 || fd2 < 0)    //只要有1个函数返回值小于0,说明打印错误
        {
                printf("open error!!\r\n");        //
                return -1;
        }

        while(1)
        {
                read_size = read(fd1,buf,512);    //读取要复制的文件,缓冲区buf地址,读取文件内容的字节大小512

                if(read_size == 0)  //如果读取到字节数量等于0,退出循环
                        break;

                write(fd2,buf,read_size); //
        }
        //用close函数关闭我们打开的文件描述符
        close(fd1); 
        close(fd2);

        return 0;
}

1、打开要复制的文件

2、创建新的文件

3、把源文件内容读到缓冲区,把缓冲区内容写入新文件

4、循坏执行第三步,直到读取的字节数量为0,退出循坏。

5、关闭打开的文件

#定义变量
#ARCH默认使用
ARCH ?= X86     

ifeq ($(ARCH),X86)
        CC=gcc

else
        CC=arm-linux-gnueabihf-gcc
endif
TARGET=copy
#OBJS=main.o mp3.o
BUILD_DIR=build
SRC_DIR=.
INC_DIR=.
CFLAG=$(patsubst %,-I%,$(INC_DIR))
INCLUDES=$(foreach dir,$(INC_DIR),$(wildcard $(dir)/*.h))


SOURCES=$(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))

OBJS=$(patsubst %.c,$(BUILD_DIR)/%.o,$(notdir $(SOURCES)))
VPATH=$(SRC_DIR)

$(BUILD_DIR)/$(TARGET):$(OBJS)
        $(CC) $^ -o $@

$(BUILD_DIR)/%.o:%.c $(INCLUDES) | create_build
        $(CC) -c $< -o $@ $(CFLAG)

.PHONY:clean create_build

clean:
        rm -r $(BUILD_DIR)

create_build:
        mkdir -p $(BUILD_DIR)
~                            

 

 sudo  mv  1.tst  1.txt   // 如果名字写错了,可以这样把它改过来哦

 

 这样就可以把1.txt的内容复制到2.txt里面


lseek函数

lseek函数的功能主要是设置文件读写位置

 使用lseek函数之前需要包含头文件#include <unistd.h>

 函数原型
off_t lseek(int fd,off_t offset,int whence)
lseek函数有三个参数

{

1.(int fd)调用open函数返回的文件描述符

2.(off_t offset):设计一个偏移量

3.(int whence):相对的基准点

若whence为SEEK_SET,基准点为文件开头
若whence为SEEK_CUR,基准点为当前位置
若whence为SEEK_END,基准点为文件末尾

返回值

如果成功:返回值等于文件偏移位置值

如果失败:返回值等于-1

}

例如:

 lseek(fd,100,SEEK_CUR);         //偏移量的位置为100个字节   基准点为当前位置

ARCH ?= X86

TARGET=test_lseek
BUILD_DIR=build
SRC_DIR=.
INC_DIR=.
CFLAG=$(patsubst %,-I%,$(INC_DIR))
INCLUDES=$(foreach dir,$(INC_DIR),$(wildcard $(dir)/*.h))

SOURCES=$(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))

OBJS=$(patsubst %.c,$(BUILD_DIR)/%.o,$(notdir $(SOURCES)))
VPATH=$(SRC_DIR)

$(BUILD_DIR)/$(TARGET):$(OBJS)
        $(CC) $^ -o $@

$(BUILD_DIR)/%.o:%.c $(INCLUDES) | create_build
        $(CC) -c $< -o $@ $(CFLAG)

.PHONY:clean create_build

clean:
        rm -r $(BUILD_DIR)

create_build:
        mkdir -p $(BUILD_DIR)

sudo vi file   //123偏移100个字节abc 


 sync函数

 页缓存和回写功能:强制把修改过的页缓存区数据写入磁盘

 使用sync函数时需要包含头文件#include <unistd.h>

 函数原型:void sync(void);
 

返回值

这个sync实验结果不明显,以后碰到再写过!

使用sync()函数就能保证write里面的数据能够及时写入磁盘里面去

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

int main()
{
        int fd = open("file",O_RDWR|O_CREAT,0666);
        write(fd,"123",3);
        lseek(fd,100,SEEK_CUR);
        write(fd,"abc",3);
        sync();
        close(fd);
        return 0;
}

 标准IO函数

C标准库实现了一个IO缓存区

常见标准IO函数

①fopen

打开一个文件

②fclose

关闭一个文件

③fread

读取文件内容

④fwrite

把内容写到文件里面去

⑤fseek

设置文件的读写位置

⑥fflush

  强制把IO缓存区的数据写入到页缓存区

文件IO五大模式

①阻塞模式
②非阻塞模式
③IO多路复用
④异步IO
⑤信号驱动IO

 


好了睡觉。。。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值