linux高级编程之文件IO管理
接上篇文章:嵌入式系统开发-麦子学院(4)——Linux C初级编程2
1. 文件IO
linux 系统中,文件IO的流程,如下图所示。
文件IO有5个函数:open()
read()
,write()
,close()
,leek()
。
1.1 open - 打开或创建一个文件*
open(char*,flag,mode)在fcntl.h
库文件中声明。
函数作用:创建或打开某个文件。
参数 | 描述 |
---|---|
char* | 包含文件名和路径 |
flag | 打开文件的方式 |
mode | 创建文件的权限 |
flag的选项有:
flag选项 | 功能 |
---|---|
O_RDONLY | 只读 |
O_WRONLY | 只写 |
O_RDWR | 读写 |
O_CREAT | 创建一个文件 |
O_EXCL | 检测文件是否存在 |
O_TRUNC | 打开文件覆盖 |
O_APPEND | 打开文件追加 |
创建文件的权限:mode &(~umask)
返回值:
成功 | 文件描述符,文件的ID号——inode |
---|---|
出错 | -1 |
1.2 close - 关闭一个文件inode
close(int inode)。
例子:touch命令的实现
#include "stdio.h"
#include "unistd.h"
#include "fcntl.h"
int main()
{
int fd;
fd = open(argv[1],O_CREAT|O_RDWR,0777);
if(fd<0)
{
printf("creat file %s failure\n",argv[1]);
return -1;
}
printf("create file %s sucess\n",fd = %d\n",argv[1],fd);
close(fd);
return 0 ;
}
1.3 write -写数据到一个文件
write(int fd,void *buf,size_t count)。在fcntl.h
库文件中声明。
参数 | 描述 |
---|---|
int fd | 当前文件的文件inode |
void *buif | 写的内容buf |
size_t count | 写多少个字节 |
返回值:实际写的字节数
1.4 read -读取一个文件的数据
read(int fd,void *buf,size_t count)
参数 | 描述 |
---|---|
int fd | 当前文件的文件inode |
void *buif | 读的内容buf |
size_t count | 读多少个字节 |
返回值:实际读的字节数
1.5 leek-读取一个文件的位置指针
leek(int fd,off_t offset,int whence)。在sys/types.h
unistd.h
库文件中声明。
作用:调整读写的位置指针。
参数 | 描述 |
---|---|
int fd | 当前文件的文件inode |
off_t offfset | 偏移量,每读写操作所移动的距离,单位是字节的数量。可正负 |
int whence | 当前位置的基点,有三个标志: ①SEEK_SET(文件的开头),②SEEK_CUR(文件指针的当前位置,③SEEK_END(文件的结尾) |
返回值:
成功 | 文件指针的当前位置 |
---|---|
出错 | -1 |
例子:cp命令的实现
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
int main (int argc, char *argv[])
{
int rd_fd,wr_fd;
char read_buf[128] = {0};
char write_buf[128] = {0};
int rd_ret = 0;
if(argc <3)
{
printf("please input src file and des file \n");
return -1;
}
rd_fd = open(argv[1],O_RDONLY);
if(rd_fd < 0 )
{
printf("open src file %s failure\n",argv[1])
return -2;
}
wr_fd = open (argv[2],O_WRONLY);
if(wr_fd <0)
{
printf("open des file %s failure\n",argv[2])
return -3;
}
while(1)
{
rd_ret = read(rd_fd,read_buf,128);
if(rd_ret < 128)
break;
write(wr_rd,read_buf,rd_ret);
memset(wr_fd,read_buf,re_ret);
}
write(wr_rd,read_buf,rd_ret);
close(rd_fd);
close(wr_fd);
}
2.标准IO
标准IO与文件IO的区别:
文件IO | 直接调用内核提供的系统调用函数,头文件是unistd.h |
---|---|
标准IO | 是间接调用系统调用函数,头文件是:stdio.h |
标准IO的实质还是通过C库函数去调用文件IO。
标准IO函数 | ||
---|---|---|
文件打开关闭 | fopen | fclose |
文件读写 | fread | fwrite |
从文件中读取/输出字符串 | fgets | fputs |
获取、输出字符串 | gets | puts |
从文件中获取、输出字符 | fgetc | fputc |
终端输出输入一个字符 | getc | putc |
输出输入一个字符 | getchar | putcahr |
格式化输入输出、从文件 | fscanf | fprintf |
从字符串 | sscanf | sprintf |
从终端 | scanf | printf |
冲刷缓存区(全缓冲、含缓冲) | fflush | |
光标定位 | fseek ftell | rewind |
文件末尾 | feof |
标准IO缓存机制:① 用户缓存 ② c库缓存 ③内核缓存
库缓存
1)全缓冲 :全缓冲指的是系统在填满标准IO缓冲区之后才进行实际的IO操作;注意,对于驻留在磁盘上的文件来说通常是由标准IO库实施全缓冲。
读:fread 写:fwrite
2)行缓冲 :在这种情况下,标准IO在输入和输出中遇到换行符时执行IO操作;注意,当流涉及终端的时候,通常使用的是行缓冲。
遇到换行符(\n)或写满缓存时,调用系统调用函数 stdout
读:fgets ,gets,printf,fprintf,sprintf
写:fputs,puts,scanf
3)无缓冲 :无缓冲指的是标准IO库不对字符进行缓冲存储;注意,标准出错流stderr通常是无缓冲的。
无缓存 stderr
1.文件的打开 fopen()
头文件:#include <stdio.h>
函数原型:
FILE *fopen(const char *path, const char *mode);
返回值: 成功 返回FILE * 类型的指针指向你要打开文件
失败 返回NULL
函数参数:const char *path ---->你要打开文件的位置
const char *mode ----》文件权限
r 以只读的方式打开文件
r+ 以可读可写的方式打开文件
w 以只写的方式打开文件,如果文件存在就清空,如果文件不存在就创建
w+ 以可读可写的方式打开文件,如果文件存在就清空,如果文件不存在就创建
a 追加,如果文件不存在就新建
a+ 以读取和追加(文件末尾的写入),如果文件不存在,则创建它。
2.文件的读写 fread() fwrite()
头文件:#include <stdio.h>
函数原型
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
返回值: 成功 返回读取到完整的数据块的个数
失败 返回0或者小于的数
判断文件是否读完不要在用返回值判断,新方式feof()判断
函数参数:void *ptr ----》存储空间名
size_t size ----》每一个数据块的大小 字节
size_t nmemb ----》打算读取多少个数据块
FILE *stream ----》文件类型的FELE *的文件指针
size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
3.文件的关闭 fclose()
头文件:#include <stdio.h>
函数原型:
int fclose(FILE *fp);
返回值: 成功 返回0
失败 返回feof()监测
函数参数:FILE *fp 文件描述符
4.判断文件的结束标志 feof()
头文件:#include <stdio.h>
函数原型:
int feof(FILE *stream);
返回值: 不等于0 ---》文件读取完毕
等于0 ---》文件没有读取完毕
5.设置文件的读写偏移 fseek()
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
返回值:成功 返回0
失败 返回-1
注意:lseek返回值和fseek()返回值意思不一样
参数:FILE *stream FILE * 文件
long offset 偏移量
int whence 偏移的位置
SEEK_SET 文件的开头
SEEK_CUR 当前的位置
SEEK_END 文件的末尾
例子:fseek(filep1,0,SEEK_SET);
long ftell(FILE *stream);
返回值:成功 返回文件当前位置距离文件开头的字节数
失败 返回-1
例子:long ftell(filep1);相当于fseek(filep1,0,SEEK_END);
void rewind(FILE *stream);//没有返回值
例子:void rewind(filp1)//等价于fseek(filep1,0,SEEK_SET)
将文件的偏移设置为起始位置
6.获取文件属性 fstat()
头文件:#include <sys/stat.h>
int fstat(int fildes, struct stat *buf);
返回值:成功 返回0
失败 返回-1
参数:int fildes 你要获取属性的那个文件的文件描述符
struct stat *buf 存放你获取到的文件属性
7.fprintf() fscanf() sprintf() sscanf()
标准输入 stdin
标准输出 stdout
标准错误输出 stderr
可变参的函数(变参函数)
#include <stdio.h>
1) int fprintf(FILE *stream, const char *format, ...);
参数:FILE *stream FILE * 文件名
const char *format 字符串
...
例子:fprintf(filep,"hello%s%d%.2f\n",buf,year,d);
//文件内容拼接
2) int sprintf(char *str, const char *format, ...);
//按照你指定的格式拼接字符串,比strcat要厉害
参数:char *str 字符串拼接指定位置
const char *format 字符串格式
...
例子:sprintf(buf0,"%sworld-%d-%d-%d",buf,year,month,day);
3) int fscanf(FILE *stream, const char *format, ...);
参数:FILE *stream FILE * 文件名
const char *format 字符串
...
往文件里面添加内容
4) int sscanf(const char *str, const char *format, ...);
//按照你指定的格式拆分字符串
参数:char *str 字符串拆分指定位置
const char *format 字符串格式
...
例子:sscanf(time,"%d-%d-%d",&year,&month,&day);//访问的是地址 &
8.fputs() fgets() fputc() fgetc() puts() gets() putchar() getchar()
#include <stdio.h>
int fgetc(FILE *stream);//从文件中读取一个字符 fread(buf,1,1,stream);
返回值:你读取到的那个字符的ASCII码
int getc(FILE *stream);//从文件当中读取一个字符
返回值:你读取到的那个字符的ASCII码
char *fgets(char *s, int size, FILE *stream);
//从文件读取size个字节的数据放到指针s中
返回值:返回读到的字符串的首地址 指针
fgets(buf,100,stdin);//获取键盘输入
int getchar(void);
//监测缓冲区的回车字符
while(getchar()!='\n')
char *gets(char *s); gets(buf);
//默认获取键盘输入的字符串
#include <stdio.h>
int fputc(int c, FILE *stream);//往文件中写入一个字符 fwrite
int putc(int c, FILE *stream);//往文件中写入一个字符 fwrite
int fputs(const char *s, FILE *stream);//相当于打印
fputs(buf,stdout);
int putchar(int c); //打印字符
putchar(a)==putchar(97)
int puts(const char *s);//打印字符串 puts(buf);
目录IO
1.1目录的打开 opendir()
头文件#include <sys/types.h>
#include <dirent.h>
函数原型:
DIR *opendir(const char *name);
返回值:成功 返回DIR类型的指针指向你打开的目录
失败 返回NULL
参数:const char *name 完整的目录路径
1.2 目录的读取 readdir()
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
返回值:struct dirent 目录结构体指针
struct dirent {
ino_t d_ino; /* 节点编号*/
off_t d_off; /* 目录的下一个偏移位置 */
unsigned short d_reclen; /* 目录大小*/
unsigned char d_type; /* 目录类型*/
char d_name[256]; /* 目录名字 */
};//存放的是目录当中的每个文件的相关信息
文件类型判断
DT_BLK This is a block device. //块设备文件
DT_CHR This is a character device.//字符设备文件
DT_DIR This is a directory.//目录文件
DT_FIFO This is a named pipe (FIFO).//管道文件
DT_LNK This is a symbolic link.//软连接文件
DT_REG This is a regular file.//普通问价
DT_SOCK This is a UNIX domain socket.//套接字文件
DT_UNKNOWN The file type is unknown.//不认识类型
1.3新建目录 mkdir
#include <sys/stat.h>
函数原型:
int mkdir(const char *path, mode_t mode);
参数:const char *path ----》你要建立的目录的路径
mode_t mode ----》新建文件的权限 0777
1.4关闭目录 closedir()
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);//结构体指针