缓存 操作对象 具体操作
标准IO 全缓存/行缓存 文件指针(流指针)FILE * 1.打开 --fopen
(库函数) 2.读写
fgetc/fputc
fgets/fputs
fread/fwrite
3.关闭
fclose
4.定位
fseek/ftell/rewind
空洞文件
文件IO 不带缓存 文件描述符 (整数) 1.打开 --open
(系统调用) 2.读写 --read/write
3.关闭 --close
4.定位 --lseek
#include
int open(const char *pathname,int flags);
int open(const char *pathname,int flags,mode_t mode);
功能:
打开或创建文件
参数:
@pathname //打开的文件名
@flags //操作的标志
//必选
O_RDONLY //只读
O_WRONLY //只写
O_RDWR //读写
//附加
O_APPEND //追加
O_CREAT //文件不存在 创建
O_TRUNC //文件存在 截短为0
@mode 一般不用
当flags中使用了 O_CREAT 时,需要指定 mode
mode 0777
0666
0444
返回值:
成功 文件描述符
失败 -1 && errno会被设置
fopen open
r O_RDONLY
r+ O_RDWR
w O_WRONLY|O_CREAT|O_TRUNC
w+ O_RDWR|O_CREAT|O_TRUNC
a O_WRONLY|O_APPEND|O_CREAT
a+ O_RDWR |O_APPEND|O_CREAT
FILE * fopen(const char *pathname,const char *mode)
{
...
if (strcmp("r",mode))
open(pathname,O_RDONLY);
}
文件创建好后的权限:
a.指定的mode
b.umask (掩码) //二进制位 --- 遮住
最终文件的权限 = ~umask & mode
0 7 7 7
111 111 111 mode
0 000 000 010
111 111 101 ~umask
------------
111 111 101
7 7 5
功能:
关闭文件描述符
以便 再次使用
参数:
@fd 要关闭的文件描述符
返回值:
成功 0
失败 -1
1.非负整型数值
2.分配原则
最小未使用
3.范围
0~1023
#include
功能:
从fd中读数据 ,存到 buf中
参数:
@fd 要读取的文件
@buf 存放读取到的数据的 内存空间
@count 一次要读取的数量(字节)
返回值:
成功 表示成功读到的字节数
失败 -1 && errno
读取结束:
0 表示到达文件结尾
#include
功能:
把buf中 写到fd中
参数:
@fd 要写入的文件
@buf 存放数据的 内存空间
@count 一次要写入的数量(字节)
返回值:
成功 表示成功写入的字节数
失败 -1 && errno
练习:
cat //文件IO 实现
1.结果输出到stdin
#include
#include
#include
int main(int argc, const char *argv[])
{
int fp;
fp = open(argv[1],O_RDONLY);
char buf[10];
int ret=0;
while((ret=read(fp,buf,sizeof(buf)-1))!=0)
{
buf[ret]='\0';
printf("%s",buf);
}
close(fp);
return 0;
}
2.结果复制到文件
#include
#include
#include
int main(int argc, const char *argv[])
{
if(argc!=3)
{
printf("Usage:%s",argv[0]);
return -1;
}
int fp1 = open(argv[1],O_RDONLY);
int fp2 = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0666);
if(fp1<0||fp2<0)
{
perror("fail open");
return -1;
}
char buf[10];
int ret=0;
while(ret=read(fp1,buf,sizeof(buf)))
{
write(fp2,buf,ret);
}
close(fp1);
close(fp2);
return 0;
}
off_t lseek(int fd, off_t offset, int whence);
功能:
重新定位文件偏移量
参数:
@fd 要定位的文件
@offset 偏移量
@whence 参考点
SEEK_SET //相对于文件开头的
offset >=0
SEEK_CUR //相对于当前位置
offset>=0
offset<0 //不能超过这个文件开头
SEEK_END //相对于文件末尾
offset < 0 //不能超过这个文件开头
offset >= 0 //可以 --- 创建 空洞 文件
返回值:
成功 从头的偏移量
失败 -1 && errno
lseek(fd,0,SEEK_SET); //定位到文件开头
lseek(fd,0,SEEK_END);
获得文件长度:
off_t len = lseek(fd,0,SEEK_END); //off_t <=> long int
eg:
创建空洞文件
给定一个文件,创建一个同样大小的空洞文件
#include
#include
#include
int main(int argc, const char *argv[])
{
if(argc!=3)
{
printf("Usage:%s",argv[0]);
return -1;
}
int fp=open(argv[1],O_RDONLY);
if(fp<0)
{
perror("fail open");
return -1;
}
int fp_h=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0666);
if(fp_h<0)
{
perror("fail open");
return -1;
}
long int len =lseek(fp,0,SEEK_END);
lseek(fp_h,len-1,SEEK_SET);
write(fp_h,"",1);
close(fp);
close(fp_h);
return 0;
}
注意:
1、不支持O_APPEND的追加模式,无法生成空洞文件。
2、lseek函数执行失败,文件指针还在偏移前的位置。
3、lseek函数在设备文件上偏移无效。 /dev/video0
4、fifo,socket 也不支持lseek的操作。
库函数: //标准IO
优点:
a.方便,功能多
b.可移植性好
标准
不足:
c.可能存在 安全性 隐患
系统调用:
优点:
a.使用起来,简单 ,功能简单
b.安全性高
c.设备文件 ---- 文件IO ///dev/video0 ----> fopen();
缺点:
c.很多复杂功能需要自己封装设计
d.可移植性差
fdopen() //将fd 转换 成 FILE *
fileno() //将FILE *转换 为 fd
功能:
将fd 转换 成 FILE *
参数:
@fd 要操作fd
@mode 打开的模式
返回值:
成功 FILE *
失败 NULL
功能:
将FILE *转换 为 fd
参数:
@stream 要转换流指针
返回值:
成功 fd
失败 - && errno
eg:
fd = open("1.txt",O_RDONLY);
FILE *fp = fdopen(fd,"a");
使用的选择:
标准IO --- 可移植性 如果操作只是文本数据
文件IO --- 安全性 操作的是硬件 ---文件IO
目录也是一种文件
类似 标准IO
//1.打开
opendir
//2.读写
readdir
//3.关闭
closedir
功能:
打开目录,关联一个目录流
参数:
@name 要打开的目录名
返回值:
成功 返回DIR *
失败 NULL & errno
功能:
读取目录项
参数:
@dirp 目录流指针
返回值:
成功 struct dirent *
失败 NULL && errno
struct dirent
{
ino_t d_ino; /* Inode number */
off_t d_off; /* Not an offset; see below */
unsigned short d_reclen;/* Length of this record */
unsigned char d_type;/* Type of file; not supported by all filesystem types */
char d_name[256]; /* Null-terminated filename */
}
功能:
关闭目录流
参数:
@dirp --- 目录流指针
返回值:
成功 0
失败 -1 &&errno
eg:
实现ls
#include
#include
int main(int argc, const char *argv[])
{
DIR * dir = opendir(argv[1]);
if(dir == NULL)
{
perror("fail open ");
return -1;
}
struct dirent *pdir = NULL;
while(1)
{
pdir=readdir(dir);
if(pdir==NULL)
{
break;
}
if((pdir->d_name[0])!='.')
printf("%s",pdir->d_name);
}
putchar('\n');
closedir(dir);
return 0;
}
eg:
shell
给定一个目录,统计目录下的 普通文件 和 目录文件的个数
#include
#include
int main(int argc, const char *argv[])
{
DIR * dir = opendir(argv[1]);
if(dir == NULL)
{
perror("fail open ");
return -1;
}
int nr=0;
int ndir=0;
struct dirent *pdir = NULL;
while(1)
{
pdir=readdir(dir);
if(pdir==NULL)
{
break;
}
if((pdir->d_type)==DT_REG)
{
nr++;
}
else if((pdir->d_type)==DT_DIR)
{
ndir++;
}
}
printf("nr=%d\nndir=%d",nr,ndir);
closedir(dir);
return 0;
}
chdir ("/home/linux"); "../../"
fopen("1.mp4")
int chdir(const char *path);// /home/linux
功能:
改变当前程序的工作路径
参数:
path:改变到的路径
返回值:
成功 返回0
失败 返回-1
/home/linux/Desktop/Music
"file.txt"
chdir("/root");
"file.txt"
char *getcwd(char *buf, size_t size);
功能:
获得当前的工作路径
参数:
buf:保存工作路径空间的首地址
size:保存路径空间的长度
返回值:
成功返回包含路径空间的字符串首地址
失败返回NULL
int a =200;
int mkdir(const char *pathname, mode_t mode);//777 666 --x--x--x
功能:
创建一个目录
666-
参数:
pathname:路径
mode:
mode & ~umask 0002
返回值:
成功 返回0
失败 返回-1
int rmdir(const char *pathname);
功能:
删除一个空目录文件
参数:
pathname:目录文件的名字
返回值:
成功 返回0
失败 返回-1