当前位置: 首页 > news >正文

第二十九天(文件io)

系统io:
我们操作这个系统就要操作这些文件
Everything is file in linux!!! -> 一切皆文件在linux这个系统里面

操作文件系统我们分为三步
将大象装进冰箱需要几步?
1 打开冰箱
2 将大象装进冰箱
3 关上冰箱

    操作文件也是基于这三步
1 打开这个文件
open
NAME
open, openat, creat - open and possibly create a file

SYNOPSIS
#include <sys/types.h>//需要的头文件
#include <sys/stat.h>
#include <fcntl.h>

       int open(const char *pathname, int flags);//打开一个文件 如果这个文件不存在则报错
int creat(const char *pathname, mode_t mode);//创建一个新的文件
int open(const char *pathname, int flags, mode_t mode);//打开一个文件,或者我们可以跟上宏来创建一个文件
pathname:路径名  你要打开这个文件在哪里
相对路径绝对路径都可以,但是你要确定能找到这个文件
如果你填的是相对路径,相对的是你的工程运行的路径
./a.out的时候会在一个文件夹,这个文件夹就是默认的工作路径
一定要记住,不是你写代码的那个文件或者你编译的那个文件夹
原型就是一个char * : 字符串
"./1.txt" "../../code/1.txt" "/mnt/hgfs/share/1.txt"
char * pathname = "/mnt/hgfs/share/1.txt";后面将pathname给open函数也可以
char buf[] = "/mnt/hgfs/share/1.txt";后面将buf给open函数也可以
char * p = malloc(128);
strcpy(p,"/mnt/hgfs/share/1.txt");//后面将p给open函数也可以
flags:打开文件的标志  这个玩意儿是实现为位域,
flags有32个bit,每一个bit上面对应一个功能,如果这个bit上面1表示这个功能打开了
否则这个功能就是关闭的
如下三个任选其一,必须要选一个
O_RDONLY    只读   
O_WRONLY    只写
O_RDWR      读写
下面的标记就根据我们的需求来
O_APPEND    追加(打开文件的时候光标会直接走到末尾)
O_CREAT     创建文件标记,如果有此标记,当文件存在的时候此标记无效
当文件不存在的时候,有此标记,会先创建这个文件再打开
如果有此标记则mode参数必给
O_EXCL标记一般和O_CREAT搭配使用,O_EXCL标记是为了测试这个文件是不是存在的
如果这个文件存在打开的时候直接报错 -> O_CREAT | O_EXCL
O_NONBLOCK  非阻塞标记
open函数打开文件默认阻塞:

                            阻塞io:有东西就读,就算实际内容没有你想读的那么多字节也读,没有东西就死等东西过来;
有空间就写,就算实际空间没有你想写的那么多字节也写,没有空间就死等空间到来。
非阻塞io:有东西就读,就算实际内容没有你想读的那么多字节也读,没有东西直接报错;
有空间就写,就算实际空间没有你想写的那么多字节也写,没有空间就死等空间到来。
各有优劣:
阻塞io的优势可以及时拿到东西,劣势执行效率很低
非阻塞io的优势执行效率高,劣势有可能不能及时拿到信息
O_TRUNC    截短标记
如果这个文件存在,并且是一个普通文件,并且打开的方式是O_RDWR or O_WRONLY,这个标记
会直接清空文件,如果只有读权限,这个标记不起作用
....还有很多的标记,有需求的时候自取
mode:创建文件的时候给的权限
给权限有两种方式
1 直接使用宏
S_IRWXU     用户读写可执行
S_IRUSR     用户只读
S_IWUSR     用户只写         
S_IXUSR     用户只执行     ->如果你想选择其中的两个S_IRUSR | S_IWUSR
S_IRWXG     组用户读写可执行
S_IRGRP     组用户只读
......
S_IRWXO     其它用户读写可执行
.....
2 8进制来给权限
0664 -> 110 110 100        
返回值:
成功返回一个 >= 0的整数,实际上没有其他的操作的情况下,一般返回值都会 >= 3
我们运行程序的时候,操作系统会默认给我们打开三个文件
标准输入文件:   STDIN_FILENO    0
标准输出文件:   STDOUT_FILENO   1
标准出错文件:   STDERR_FILENO   2
这个整数非常的重要,后续操作这个文件都是通过这个整数,这个整数我们叫文件描述符(fd)
失败返回返回-1,同时errno被设置
errno:是系统的全局设置错误值的变量,当系统接口出现错误的时候都会设置这个变量
我们需要一个错误解析的函数来解析我们的错误值
NAME
perror - print a system error message

                        SYNOPSIS
#include <stdio.h>

                            void perror(const char *s);
s:程序员自己写的一个标记,
"hehe sb250"
这个函数的调用结果为
先将标记打印:系统的错误信息
每一个系统接口都有可能会出错(出错不是错误),每调用一个系统接口都需要判断是否出错
int fd1 = open(1.txt)
if(-1 == fd1)
{
perror("1.txt error");
}
int fd2 = open(2.txt)
if(-1 == fd2)
{
perror("2.txt error");
}


2 操作文件(对文件进行读写)
read/write   操作文件的时候,读写的位置都是基于一个叫光标的东西
open打开文件的时候光标默认是在开头的,每读写一个字节,光标就会往后面走一个
NAME    在一个文件描述符上面执行读的操作
read - read from a file descriptor

SYNOPSIS
#include <unistd.h>

       ssize_t read(int fd, void *buf, size_t count);
fd:    文件描述符 你要读哪个文件
buf:   你读到的内容放在哪里保存 --- 就是程序员开辟的内存空间
count: 你要读多少个字节  单位是字节,1就是1个字节  10000就是10000个字节
返回值:成功返回实际读到的字节数 <= count
失败返回-1,同时errno被设置
如果返回值是0表示你读到了文件的末尾你再读返回的就是0

NAME    在一个文件描述符上面执行写的操作
write - write to a file descriptor

SYNOPSIS
#include <unistd.h>

       ssize_t write(int fd, const void *buf, size_t count);
fd:文件描述符 你要往哪个文件里面写
buf:你要写什么玩意儿  一个内存
count:你要写多少个字节
返回值:成功返回实际写入的字节数( <= count)
失败返回-1,同时errno被设置
写入的时候也是基于光标位置,写的时候是覆盖,不是往后面挤

        3 关上这个文件
close
NAME
close - close a file descriptor

SYNOPSIS
#include <unistd.h>

       int close(int fd);
fd:你要关闭的文件


练习:
做文件到文件的复制操作,将一个文件里面的所有的内容搬到另外一个文件
操作如下
前面的这个文件必须存在   后面的这个文件如果存在则截短,如果不存在则创建
一个字节不多,一个字节不少
./mycp ./1.mp3 ../../code/2.mp3
赋值文件就像搬砖
1 一块一块的搬 -- 但是效率很低
2 将全部的砖一次搬完 -- 但是你可能没那么大的力气
3 一次搬一车砖 --- 效率也有,你也能实现
这个车子就是我们的容器,对应的就是内存空间
开一个较大的内存,每次都搬这么多字节,搬完为止 --- 没得搬了就搬完了


lcd点阵,给你们的开发板的屏幕分辨率是1024 * 600的
有600行,每行有1024个像素点
像素点由三原色构成   r  g  b
系统对于每个像素点的描述多一个分量 -- 透明度  a
所以在系统里面我们用argb来表示一个颜色
现在我们要描述一个颜色 --- 我们用4个字节的整数来描述一个颜色 --- 颜色的量化
一个颜色是4个字节,有4个分量,因此每个分量都是1个字节
没有符号,全都是数值为,因此我们一般采用16进制来描述一个颜色
这4个分量是有严格的顺序  最高字节为a  次高字节为r  次低字节为g 最低字节为b
每个分量的取值范围为 0 ~ 255,0代表没有 依次递增  255代表最大
透明度只代表是否透明,因此设置多少跟颜色没有关系
r = 0x00 -> 红色没有
g = 0xff -> 绿色达到最亮
b = 0x7f -> 蓝色的那个灯只有全亮的一半亮
这三个颜色组合在一起就合成了我们屏幕显示的所有的颜色 
总共可以显示 256 * 256 * 256
0xff00 -> 全绿    0x1200 -> 绿的不是那么亮

            0x12345678 -> 偏蓝色,天蓝色


我现在要操作屏幕,而屏幕是1024* 600的,每个像素点4个字节
我想屏幕成为什么颜色,就写什么颜色值,将1024 * 600个int值写入到屏幕
屏幕就会显示成我们希望的颜色
/dev/fb0

    1 打开屏幕那个文件

    2 往屏幕里面写入1024* 600个int


3 close屏幕

NAME
ioctl - control device  操作驱动

SYNOPSIS
#include <sys/ioctl.h>

       int ioctl(int fd, unsigned long request, ...);
fd:文件描述符
request:指令
现在我们要获取屏幕的分辨率 ,linux/fb.h里面可以知道  
我们操作命令FBIOGET_VSCREENINFO
第三个参数:根据第二参数不一样,第三个参数会变
我们的第二个参数FBIOGET_VSCREENINFO
那么第三个参数就是struct fb_var_screeninfo 结构体指针
获取数据,获取到的数据写入到这个结构体


NAME
lseek - reposition read/write file offset
设置偏移量(光标位置)
SYNOPSIS
#include <sys/types.h>
#include <unistd.h>

       off_t lseek(int fd, off_t offset, int whence);
fd:文件描述符
offset:偏移量  可正可负  单位是字节
正代表向后
负代表向前
whence:基准定位  先看基准定位,定位好了再看offset来进行微调
SEEK_SET    文件的开头,如果offset写了一个负数,这个时候会留下一个空洞
空洞需要警惕
SEEK_CUR    为光标当前位置
SEEK_END    文件的末尾,如果offset写了一个正数,这个时候会留下一个空洞
返回值:
成功返回光标偏移好了的位置到文件开头所有的字节数
我们可以依次求文件的大小 int filesize = lseek(fd,0,SEEK_END);
失败返回-1,同时errno被设置

练习:
1 显示一个其它颜色到开发板
2 轮流显示不同的颜色,一直显示,不会停止


作业:不需要交
给你一个bmp图片文件,请根据bmp图片格式
获取如下信息
是不是bmp图片的头部,如果不是bmp图片请提示
如果是真的bmp图片再获取如下信息
宽度 高度  色深

// 给你一个bmp图片文件,请根据bmp图片格式
//         获取如下信息
//             是不是bmp图片的头部,如果不是bmp图片请提示
//             如果是真的bmp图片再获取如下信息
//                 宽度 高度  色深
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <stdlib.h>int main(int argc, char *argv[])
{int fd = open("../pic/1.bmp",O_RDWR,0664);if(-1 == fd){perror("open 1.bmp error");return -1;}printf("open 1.bmp success\n");char buf[1024];int r = read(fd,buf,1024);if(-1 == r){perror("read 1.bmp error");return -1;}if(buf[0] == 'B' && buf[1] == 'M'){printf("read 1.bmp success\n");}else{printf("不是bmp图片文件\n");}printf("开始读取文件内容\n");lseek(fd,0x12,SEEK_SET);int w;read(fd,&w,4);printf("宽度:%d\n",w);lseek(fd,0x16,SEEK_SET);int h;read(fd,&h,4);printf("高度:%d\n",h);lseek(fd,0x1c,SEEK_SET);int color_depth;read(fd,&color_depth,2);printf("颜色深度:%d\n",color_depth);close(fd);return 0;}

http://www.dtcms.com/a/326834.html

相关文章:

  • Android视频编辑方案测评:轻量化剪辑工具的性能表现
  • 基于51单片机红外遥控定时开关智能家电插座设计
  • golang 基础案例_02
  • 算法知识笔记
  • 学习日志31 python
  • 【C++】STL——priority_queue的使用与底层模拟实现
  • 查看 php 可用版本
  • Nestjs框架: RBAC基于角色的权限控制模型初探
  • STM32TIM定时器
  • 请求报文和响应报文(详细讲解)
  • Wed前端第二次作业
  • C语言增删查改实战:高效管理顺序表
  • docker安装searxng
  • monorepo架构设计方案
  • CICD部署流程详解文档笔记
  • 在 Ubuntu 中docker容器化操作来使用新建的 glibc-2.32
  • [激光原理与应用-244]:设计 - 光学 - CLBO晶体使用一段时间后,输出功率就会下降,原因有哪些?
  • OpenBMC中的snk-psu-manager:架构、原理与应用深度解析
  • 高防IP能为网站防御哪些网络攻击?
  • 从零开始学JAVAWeb-5
  • 腾讯云Edgeone限时免费
  • for循环详解与实战技巧
  • Edit Distance
  • 传统制造业减人不减效:一线用工优化的3个投入方向,用对工具比盲目裁员更关键
  • 对抗样本攻击检测与防御
  • 车载软件架构 --- 车辆量产后怎么刷写Flash Bootloader
  • BLE ADV
  • special topic 9 (2) and 1011(1)division one
  • 深入解析Windows系统下UDP绑定失败的原理与系统级解决方案
  • 数据库三范式入门教程