目录
1. 文件操作
Linux下的一切设备都是文件操作。
声卡、LCD显示屏、鼠标、键盘----->都是一个文件。
文件操作操作分为:缓冲和非缓冲操作。
(1)常用的跟文件相关的命令
cat:读文件 touch:创建文件 vi、vim、gedit:编辑文件 |
(2)缓冲和非缓冲的区别
缓冲形式的文件操作函数(带有f的):fopen、fread、fwrite、fclose………… 用途:一般用来操作普通的文件。 数据放在DDR内存空间(RAM)。 非缓冲的文件操作:open、read、write、close………… 用途:一般来操作驱动设备文件。 缓冲,意味着实时性要求不是很强。因为设备驱动中,要求设备驱动能实时响应用户程序的行为,所以使用的是非缓冲形式的文件。 |
注:带f的是C语言标准库,不带f的是linux内核里面的函数。
2. 非缓冲文件操作
Linux下设备驱动专用的操作!
2.1 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, mode_t mode); //带权限地打开或者创建 int creat(const char *pathname, mode_t mode); //创建文件 |
API的参数:
(1)const char *pathname :文件的路径和名称。 字符串的形式
比如:”/work/123.c”
这里需要注意C和C++路劲的不同写法。
(2)flags 的可选项如下所示:
O_RDONLY :0x0000 以只读的方式打开文件或者设备 O_RDWR :0x0002 以读写的方式打开------创建管道文件的时候,必须是这种方式 。 O_EXCL :0x0400 仅与 O_CREAT 连用,如果文件已存在,则强制 open 失败 |
注:该参数可以使用|,同时设备文件的多个属性。
比如: int fd=open(“./123.c”,O_RDWR|O_CREAT);
(3)返回值:
返回值是一个小整数。这个整数称为文件描述符fd。这个文件描述符相当于一个文件信息结构的索引!
>0 :表示文件打开成功。 <0 :表示文件打开失败。 文件描述符会存放在映射表。----linux内核机制 file_info[10]; |
(4)mode_t mode:决定创建文件的权限!mode 的可选项:
S_IRWXU 权限,代表该文件所有者具有可读(R)、可写(W)及可执行(X)的权限。 S_IRWXG 00070 权限,代表该文件用户组具有可读、可写及可执行的权限。 S_IRWXO 00007 权限,代表其他用户具有可读、可写及可执行的权限。 |
2.2 read / write函数
所有对文件的操作的前提是,文件要先成功打开。
在linux里面查看帮助:
# man 2 read
数字2表示查看第2页的帮助信息,控制台打印输出如下:
#include <unistd.h> ssize_t read(int fd, void *buf, size_t count); ssize_t write(int fd, const void *buf, size_t count); |
(1)参数
int fd :文件描述符。Open的返回值。 void *buf :存放读出的数据缓冲区和写数据的缓冲区 size_t count :读出的字节数和写字节数 |
返回值:读写成功的字节数量。
注:
(1) 对普通文件/设备文件的读写之前,都要先打开,获得文件描述符,才能进行读写操作。
(2)缓冲区:是以字节为单位。
读:是读出打开的文件的数据,那么读出来了,放到哪里?放到缓冲区;
写:是将已经存在的数据(缓冲区里面的)写入已经打开了的文件;
2.3 关闭文件close函数
#include <unistd.h> int close(int fd); |
功能:关闭打开的文件。
参数:打开文件时,open()函数返回的文件描述符。
返回值:
close() returns zero on success. On error, -1 is returned, and errno is set appropriately. |
2.4 指针移动文件
#include <sys/types.h> #include <unistd.h> off_t lseek(int fd, off_t offset, int whence); |
功能:移动文件指针;文件指针会按照偏移量(字节为单位),进行偏移。
参数:
int fd :open()的返回值。 off_t offset :偏移的属性(从哪里开始偏移)。 SEEK_SET :文件头开始 SEEK_CUR :当前位置 SEEK_END :文件结尾 int whence :偏移的字节数。 |
2.5 标准main函数写法------带两个参数
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> //一般有两种写法 int main(int argc,char**argv) // int main(int argc,char*argv[]) {
} |
int argc :表示传入的参数数量
char**argv :存放传入的参数缓冲区。注意:传入的参数都是以字符串的形式存在。缓冲区的数组下标从0开始的。
注:特殊之处在于缓冲区由系统分配和管理,不需要用户自定义;一个参数就是一个串,串与串之间空格隔开。
示例1:
#include<stdlib.h> #include<stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main(int argc,char **argv) { int count=0; printf("总共传入了%d个参数\n",argc); for(;count<argc;count++) { printf("第%d个参数:%s\n",count,argv[count]); } return 0; } |
代码运行
#./a.out 123 456 789 argc = 4 argv[0] =”a.out” argv[1]=”123” argv[2]=”456” |
示例2:
#include <stdio.h> #include <stdlib.h> Int main(int argc ,char *argv[]) { int i=0; printf("argc=%d\r\n",argc); for(;i<argc;i++) { printf("arcv[%d]=%s\r\n",i,argv[i]); } return 0; } 在PC机linux下,编译并测试如下: [root@localhost test]# ./main 123 456 789 argc=4 arcv[0]=./main arcv[1]=123 arcv[2]=456 arcv[3]=789 在嵌入式平台下编译并测试: 在宿主机上进行编译: [root@localhost test]# arm-linux-gcc main.c -o arm-mian [root@localhost test]# ls arm-mian main main.c 在开发版中运行: [root@WGP /test]# ls arm-mian main main.c [root@WGP /test]# ./arm-mian 1234 456 789 argc=4 arcv[0]=./arm-mian arcv[1]=1234 arcv[2]=456 arcv[3]=789 [root@WGP /test]# |
关于字符编码:Linux下通常会使用的文字编码:UTF-8 。Windows下默认使用的编码:GB2312 、(GBK) ;简称 936。
2.6 字符串转整数
比较简单的函数:
#include <stdlib.h> int atoi(const char *nptr); //字符串转为整数 long atol(const char *nptr); long long atoll(const char *nptr); long long atoq(const char *nptr); |
示例1:
#include <stdio.h> #include <stdlib.h> Int main(int argc ,char *argv[]) { int data; data=atoi((char *)argv[1]); printf("data=%d\r\n",data+1); return 0; } 测试如下: [root@localhost test]# ./main 2 data=3 [root@localhost test]# ./main 222 data=223 |
字符串格式化输出:
#include <stdio.h> int sprintf(char *str, const char *format, ...); int snprintf(char *str, size_t size, const char *format, ...); |
2.7 实现cat命令
实现cat命令相同的功能(相当于自己写一个cat命令,名称cat_1)
./cat 123.txt
示例代码如下:
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int main(int argc ,char**argv[]) { char *file_buff=NULL; if(argc!=2) { printf("format:./app [filename]\r\n"); exit(-1); } int fd=open((char *)argv[1],O_RDWR|O_CREAT); if(fd<0) { printf("file_open_fail\r\n"); } struct stat st; if(stat((char *)argv[1],&st)==-1) { printf("can not get size of file\r\n"); exit(-1); } else { printf("byte=%d\r\n",st.st_size); file_buff=(char *)malloc((st.st_size+1)*sizeof(char)); if(file_buff==NULL) { printf("fail to malloc\r\n"); exit(-1); } } //char *str=file_buff; int re_fd=0; while(1) { re_fd=read(fd,file_buff,st.st_size); file_buff[re_fd]='\0'; while(*file_buff!='\0') { printf("%c",*file_buff++); } file_buff-=re_fd; //free(str); re_fd=0; break; } close(fd); return 0; } 测试: [root@localhost test]# ls 12.txt main.c rm.sh [root@localhost test]# gcc main.c -o cat [root@localhost test]# ls 12.txt cat main.c rm.sh [root@localhost test]# ./cat 12.txt byte=52 123456789101112131415161718192021222324252627282930 [root@localhost test]# 注:
|
2.8 实现cp命令
实现cp命令相同的功能。
cp 123.txt 456.txt 结果:将123.txt拷贝到456.txt文件中。
示例代码:
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> main(int argc ,char *argv[]) { char *file_buff=NULL; if(argc!=3) { printf("format:./app [op_filename] [wr_filename]\r\n"); exit(-1); } int op_fd=open((char *)argv[1],O_RDWR|O_CREAT); if(op_fd<0) { printf("opfile_open_fail\r\n"); exit(-1); } int wr_fd=open((char *)argv[2],O_RDWR|O_CREAT); if(wr_fd<0) { printf("wrfile_open_fail\r\n"); exit(-1); } struct stat st; if(stat((char *)argv[1],&st)==-1) { printf("can not get size of opfile\r\n"); exit(-1); } else { printf("opfile_byte=%d\r\n",st.st_size); file_buff=(char *)malloc((st.st_size+1)*sizeof(char)); if(file_buff==NULL) { printf("fail to malloc\r\n"); exit(-1); } } int re_count=0; int wr_count=0; while(1) { re_count=read(op_fd,file_buff,st.st_size); wr_count=write(wr_fd,file_buff,re_count); if(re_count==wr_count) { re_count=0; wr_count=0; free(file_buff); printf("successful\r\n"); break; } else { re_count=0; wr_count=0; free(file_buff); printf("fail\r\n"); break; } } close(op_fd); close(wr_fd); return 0; } 测试如下: [root@localhost test]# ls 12.txt 34.txt main.c rm.sh [root@localhost test]# gcc main.c -o cp [root@localhost test]# ls 12.txt 34.txt cp main.c rm.sh [root@localhost test]# ./cp 12.txt 34.txt opfile_byte=52 successful [root@localhost test]# |
2.9 初始化缓冲区
#include <string.h> void *memset(void *s, int c, size_t n); 参数: void *s :缓冲区的首地址 int c :填充的数据值 size_t n :填充的长度,以字节为单位。 |
3. 带缓冲的文件操作
C语言标准文件操作!带缓冲的文件操作 都是对文件指针操作!
3.1 打开文件fopen
#include <stdio.h> FILE *fopen(const char *path, const char *mode); FILE *fdopen(int fd, const char *mode); |
参数:
const char *path :文件的路径。 const char *mode :模式 |
返回值:打开成功返回对应的文件指针。失败返回NULL。
mode 模式可选的值:
模式 | 读 | 写 | 位置 | 截断原内容 | 创建 |
rb | YES | NO | 文件头 | NO | NO |
r+b | YES | YES | 文件头 | NO | NO |
wb | NO | YES | 文件头 | YES | YES |
w+b | YES | YES | 文件头 | YES | YES |
ab | NO | YES | 文件尾 | NO | YES |
a+b | YES | YES | 文件尾 | NO | YES |
注:如果选择“截断原内容”,则操作的目标文件的原来的内容会被清空!
3.2 读写函数
#include <stdio.h> size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream); |
参数:
void *ptr :读写的缓冲区指针。 size_t size :数据包的大小(单个)。 size_t nmemb :数据包的数量(总的)。 FILE *stream :fopen的返回值。 |
返回值:读写成功的数据包数量。
注:带缓冲的,是分包进行读写或者发送的。
示例:
//写1024个数据到123.c 。 fwrite(ptr,1024 ,1 ,stream); //一次写1024个字节,写一次。 fwrite(ptr,1,1024 ,stream); //一次写1个字节,写1024次。 |
参数2 3之间是一种耦合关系。
3.3 关闭文件
#include <stdio.h> int fclose(FILE *fp); |
功能:关闭打开的文件。释放文件指针占用的空间。
4. 目录操作
4.1 打开目录
#include <sys/types.h> #include <dirent.h> DIR *opendir(const char *name); |
参数:const char *name ,目录的路径。
返回值:成功则返回DIR * :打开的目录指针,失败就返回值空指针 NULL。
4.2 读目录
#include <dirent.h> struct dirent *readdir(DIR *dirp); |
形参:
DIR *dirp :opendir函数返回值。
返回值:正常返回struct dirent *指针,失败返回空。
struct dirent { ino_t d_ino; /* inode number */ off_t d_off; /* offset to the next dirent */ unsigned short d_reclen; /* length of this record */ unsigned char d_type; /* type of file; not supported by all file system types */ char d_name[256]; /*文件的名称*/ }; |
4.3 关闭目录
#include <sys/types.h> #include <dirent.h> int closedir(DIR *dirp); |
实现的功能: 遍历出指定目录下的所有文件。
C89标准 、C99标准 、C11标准
C99标准:1999年国际标准化组织颁布的C语言官方标准第二版。 C99标准:2011年国际标准化组织颁布的C语言官方标准第三版。 GCC编译器支持C11 |
练习:实际应用-->图片浏览器 --->视频播放器--->音乐播放器。
题目:列出指定目录下的文件。比如: xxx.bmp 、xxx.mp4 、 xxx.MP3
基础:先实现打印出完整路径。
./a.out /etc/
打印的完整路径效果:/etc/1.c /etc/2.txt
示例代码:
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <dirent.h> #include <string.h> int main(int argc ,char *argv[]) { if(argc!=3) { printf("./app [dirname] [file.end]\r\n"); exit(0); } DIR *dir=NULL; dir=opendir(argv[1]); if(dir==NULL) { printf("fail_to_opendir\r\n"); exit(0); } struct dirent *dir_data; int count=0; char *dir_name; char *p; while(dir_data=readdir(dir)) { if(p=strstr(dir_data->d_name,argv[2])) { dir_name=malloc(strlen(argv[1])+strlen(dir_data->d_name)+1); strcpy(dir_name,argv[1]); strcpy(dir_name,dir_data->d_name); count++; printf("%d:%s\r\n",count,dir_name); free(dir_name); } } closedir(dir); return 0; } 测试如下: [root@localhost test]# ls 12.txt 34.txt a.out dir.c dir.c~ rm.sh [root@localhost test]# ./a.out ./ .txt 1:12.txt 2:34.txt [root@localhost test]# ./a.out ./ .c 1:dir.c 2:dir.c~ |
下一篇:示例代码