课程概览
===============
1.学习方法:学接口函数(返回值,功能,形参)
2.系统IO相关的函数
标准IO相关的函数
目录操作相关的函数
系统IO函数
==============
IO:input output文件的输入和输出
嵌入式中有大量的硬件设备(液晶屏,触摸屏,键盘)
linux中一切都是文件: /dev
open() read() write close lseek stat dup dup2
(1)文件的打开或者新建
#include
#include
#include
int open(const char *pathname, int flags);
返回值:成功返回文件描述符或者翻译成文件的句柄(重点,替身)
专业理解:文件描述符就是数组的下标(系统中定义一个专门存放打开文件属性信息的结构体数组)
非专业理解:文件描述符就是替身
失败 -1
参数:pathname --》你要打开、新建的文件的路径名
flags --》O_RDONLY, O_WRONLY, or O_RDWR. 宏定义
用什么权限打开文件
int fd=open("/home/gec/1.txt",O_RDWR);
int open(const char *pathname, int flags, mode_t mode); //新建文件的同时可以设置文件的权限
参数:mode --》设置权限的,用八进制的数字表示权限
flags --》O_CREAT 新建文件
O_EXCL 配合O_CREAT一起使用,表示如果新建的文件已经存在就返回-1并退出
O_TRUNC 配合O_CREAT一起使用,表示如果新建的文件已经存在就清空覆盖掉原来的文件
open("/home/gec/new.txt",O_CREAT,0777);
总结:linux中只要函数参数有多个宏定义让你选择
你如果要使用多个宏,都是用按位或连接起来
系统IO
=================
在共享里面用chmod修改权限是不准确的(windows跟linux公用的环境,修改权限,创建软链接都会有问题)
rwxrwxrwx 1 root root 33 Jan 13 22:08 1.txt
touch命令:
新建文件,但是无法打开文件
/usr/src/linux-headers-3.5.0-23-generic/include/linux/sched.h的第1394行定义结构体指针,专门用来指向打开成功的文件信息(结构体数组)
(2)读取文件内容
fd=open("1.txt") 文件描述符和文件名本身之间一一对应的映射关系
typedef 给常见的类型换了新名字,例如mode_t size_t ssize_t off_t
#include
ssize_t read(int fd, void *buf, size_t count);
返回值:成功读取的字节数 失败 -1
文件读取完毕返回0
fd --》文件或者硬件设备的文件描述符
buf --》可以接收任意类型指针作为实参,存放你读取到的文件内容
count --》你打算读取多少字节的数据
(3)写入文件
#include
ssize_t write(int fd, const void *buf, size_t count);
返回值:count写多少,返回值就是多少 失败 -1
注意问题:count不要随便乱写
(4)文件的关闭
int close(int fd);
(5)设置文件读写偏移(设置光标位置)
off_t lseek(int fildes, off_t offset, int whence);
返回值:当前光标距离文件开头的字节数 失败 -1
参数:fildes --》你要设置偏移的文件的文件描述符
offset --》你打算偏移多少字节
whence --》SEEK_SET -->起始位置
SEEK_CUR -->当前位置
SEEK_END -->文件末尾
例如:lseek(fd,0,SEEK_END); 返回值就是文件的大小,记得求出大小以后,重新将光标移动回起始位置
lseek(fd,-5,SEEK_END);
练习:
1.拷贝文件 -->通过主函数传参拷贝一个文件
./main 1.txt 2.txt
1.txt本来就有(字节数要求多一点,例如拷贝我们的某一天的笔记)
2.txt没有
2.open("1.txt") ,打印文件描述符
open("2.txt") ,打印文件描述符
关闭1.txt
open("3.txt") ,打印文件描述符
3. lseek(fd,-5,SEEK_SET);
lseek(fd,-5,SEEK_CUR);
4. 要求将文件最后面十个字节的内容,以及倒数第50到60这十个字节的数据拷贝到另外一个文件中
./main 1.txt
5. 在开发板上显示bmp格式的图片
bmp格式图片特点:
1.每个像素点占3个字节
2.bmp格式是微软公司发明的,存储的时候颜色值颠倒BGR
3.存储的时候上下也是颠倒的
机器视觉 -->图像处理 opencv openGL
系统IO
=================
vim新建文件,会有隐藏字符,你可以在/etc/vim/vimrc配置文件中,加上set list这句话,显示隐藏的字符
(6)获取文件属性信息(比如:文件的权限,文件的大小)
#include
#include
#include
int stat(const char *path, struct stat *buf); //不能够判断软链接
int lstat(const char *path, struct stat *buf); //能够判断软链接
返回值:成功 0 失败 -1
参数:path --》文件的路径名
buf --》存放你获取到的文件的属性信息
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */ linux将目录中所有的内容用类似链表的存储结构,每个节点都有一个编号
mode_t st_mode; /* protection */ 存放文件的权限信息,文件类型信息(重点)
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */ 字符设备或者块设备
off_t st_size; /* total size, in bytes */ 文件大小
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */ 最后访问时间
time_t st_mtime; /* time of last modification */ 修改时间
time_t st_ctime; /* time of last status change */ 状态改变时间
};
S_IRWXU 00700 mask for file owner permissions
S_IRUSR 00400 owner has read permission
S_IWUSR 00200 owner has write permission
S_IXUSR 00100 owner has execute permission
S_IRWXG 00070 mask for group permissions
S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IXGRP 00010 group has execute permission
S_IRWXO 00007 mask for permissions for others (not in group)
S_IROTH 00004 others have read permission
S_IWOTH 00002 others have write permission
S_IXOTH 00001 others have execute permission
S_ISREG(m) is it a regular file?
S_ISDIR(m) directory?
S_ISCHR(m) character device?
S_ISBLK(m) block device?
S_ISFIFO(m) FIFO (named pipe)?
S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.)
S_ISSOCK(m) socket? (Not in POSIX.1-1996.)
(7)文件重定向
标准输出:lcd printf打印的内容
标准错误输出:lcd perror打印
int dup(int fildes); //给旧的文件描述符,分配新的文件描述符
返回值:新的文件描述符 失败 -1
参数:fildes --》原本旧的的文件描述符
int dup2(int fildes, int fildes2);
(8)错误码
原理:linux中定义一个全局变量errno,保存了linux系统中所有常见的错误类型
linux头文件中将所有的出错定义成了宏,errno保存某个出错的宏定义
/usr/include/asm-generic/errno.h定义了一部分错误的宏
#include
#include
void perror(const char *s); //将错误的原因也打印出来
参数:s --》打印信息
(9)修改权限
int chmod(const char *path, mode_t mode);
练习:
主函数传参传递路径
检查参数个数 --》不符合要求退出,让用户传参
检查文件类型 --》普通文件,要求获取文件大小,并判断文件的权限是不是当前用户可读可写
如果权限不符合要求使用chmod()函数修改权限为可读可写,然后拷贝
目录,退出程序,提示用户,文件类型不符合要求
标准IO
=================
标准IO和系统IO
主要区别:系统IO open read write close 不带读写缓冲
标准IO fopen fread fwrite fclose 带缓冲
(1)打开文件
FILE *fopen(const char *path, const char *mode);
返回值:成功返回FILE类型的指针用来存放文件的信息
失败 NULL
参数:mode --》r 只读的方式打开
r+ 可读可写的方式打开
w 如果文件不存在,可以新建
如果文件存在,清空 可写的方式打开
w+ 如果文件不存在,可以新建
如果文件存在,清空 可读可写的方式打开
a 追加的方式打开文件,不存在,新建
a+ 追加的方式打开文件,不存在,新建
(2)文件的读写
ssize_t read(int fd, void *buf, size_t count);
read(fd,buf,100);
fread(buf,10,10,myfile);
fread(buf,25,4,myfile);
fread(buf,100,1,myfile);
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
以数据块为单位读
返回值:重点 成功读取到的完整的数据块的个数
参数:size --》每个数据块的大小 字节
nmemb --》你打算读取多少个数据块
size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
返回值:重点 在没有超出缓冲区大小的情况下 nmemb写多少,返回值就是多少
标准IO
================
硬件的驱动:用系统IO操作
读写一个普通文件:建议你用标准IO,带缓冲速度快
(4)关闭
int fclose(FILE *fp);
(5)字符串的拼接和拆分
sprintf() //字符串的拼接,可以将任意类型的数据拼接成字符串(*****重点)
int sprintf(char *str, const char *format, ...); //可变参数函数
参数:str --》存放拼接得到的字符串
format --》你想按照什么格式去拼接字符串
注意:str大小一定要足够存放结果
sscanf() //字符串拆分
int sscanf(const char *str, const char *format, ...);
参数:str --》你要拆分的字符串
format --》你打算按照什么格式拆分
(6)刷新缓冲区,区分系统IO(不带缓冲区)和标准IO(f开头的那些函数,带缓冲区)
int fflush(FILE *stream);
(7)求缓冲区大小
系统中/usr/include/stdio.h 第49行类型重定义了FILE
/usr/include/libio.h 第273行就有结构体的完整定义
linux中将缓冲分为三种:不带缓冲,全缓冲,行缓冲
全缓冲:等待缓冲去填满,才进行IO操作,普通文件
A 当缓冲区被填满时,立即刷新
B 当调用fflush( )时,立即刷新
C 当调用setbuf( )/setvbuf( )时,立即刷新
D 当进程正常关闭时,立即刷新(暂时不管)
D.1 在main函数中return
D.2 调用exit( )/_exit( )/_Exit( )
D.3 在最后一条线程中调用pthread_exit( )
E 当调用fclose( )时,立即刷新
行缓冲:等待一行结束 \n,进行IO操作,或者行缓冲区满了,刷新,标准输出(屏幕),标准IO
A 当缓冲区被填满时,立即刷新
B 当调用fflush( )时,立即刷新
C 当调用setbuf( )/setvbuf( )时,立即刷新
D 当进程正常关闭时,立即刷新
D.1 在main函数中return
D.2 调用exit( )/_exit( )/_Exit( )
D.3 在最后一条线程中调用pthread_exit( )
E 当调用fclose( )时,立即刷新
F 当遇到'\n'时,立即刷新
(8)设置文件读写的偏移
int fseek(FILE *stream, long offset, int whence);
long ftell(FILE *stream); //返回文件当前位置距离文件开头的字节数
void rewind(FILE *stream); //等价于fseek(filep,0,SEEK_SET);
C语言:long整型 long m=12;
long m=12L;
(9)fgets() fputs() gets() puts() getchar() putchar() getc() putc()
第一组:fgets() fputs()
总结:fgets(buf,size,filep);
size没有超出文件一行的大小,buf中最后面填充'\0'
size超过了文件一行的大小,buf中最后面将回车(windows上\r\n)以及'\0'补充在后面
(linux上\n)
char *fgets(char *s, int size, FILE *stream); //读取一行数据
返回值:读取到字符串的首地址 失败 NULL
参数:s --》存放读取到的字符串
int fputs(const char *s, FILE *stream); //写入一行数据
第二组:gets() puts()
char *gets(char *s); //只能从键盘读取字符串
int puts(const char *s); //只能写入到标准输出(液晶屏)
第三组:getchar() putchar()
int getchar(void);
int putchar(int c); //只能是写入一个字符到lcd
返回值:对应字符的ASCII值
参数:c --》你要写入的字符的ASCII值
第四组:getc() putc()
int getc(FILE *stream);
getc(stdin); 从键盘读取一个字符,返回字符的ASCII码值
getc(filep); 从filep代表的文件中读取一个字符
int putc(int c, FILE *stream);
putc('y',stdout); //将y打印在屏幕上
putc('y',filep); //将字符y写入到filep代表的文件中