本文内容:系统IO 、标准IO、目录操作
1.课程概览
核心内容:使用linux中提供一系列函数(API),去操作linux当中的文件
(新建文件、打开文件、读写文件、关闭文件)
我们发现前面我已经学过如何操作文件:
使用命令来操作:vi touch gedit vim
使用函数接口来写代码进行操作:
2.基本概念
1.在linux中一切都是文件
对于操作系统来说:硬件设备-----》只使用驱动(可执行的二进制文件)
既然所有的东西都可以抽象为文件,我们很有必有学习文件IO.
2.linux中对文件的分类 ls -l查看的
普通文件 -
目录文件 d(directory)
软连接文件 l(link)
管道文件 p(pipe) 进程间通信
套接字文件 s(socket)网络通信
字符设备文件 c 驱动
块设备文件 b 驱动(U盘、硬盘)
3.相关的接口函数----》man手册----》按字母‘q’退出手册
1 Executable programs or shell commands//linux的系统命令
2 System calls (functions provided by the kernel)//linux内核提供的函数
3 Library calls (functions within program libraries)//C语言库函数
(1)系统IO(操作系统提供的函数)
1.1文件的打开和新建----》open()
头文件:#include
#include
#include
函数原型:
int open(const char *pathname, int flags);
函数返回值:
成功 返回一个文件描述符(替身)>=0
失败 返回 -1
函数参数:const char *pathname --->你要打开的文件所在的位置
int flags(宏定义)---》O_RDONLY read 只读权限
O_WRONLY write 只写权限
O_RDWR read and write 可读可以
O_CREAT creat 新建一个文件
O_EXCL 跟O_CREAT配合,如果有新建文件的时候,文件存在,就退出
O_NOCTTY 无权限默认属性
O_TRUNC 跟O_CREAT配合,如果有新建文件的时候,文件存在,就覆盖
int open(const char *pathname, int flags, mode_t mode);
形参:mode
注意:权限mode满足这个公式 mode & ~umask
设置权限只能在纯粹的linux环境使用才能生效
用户组
S_IRWXU 00700 user has read, write and execute permission
S_IRUSR 00400 user has read permission
S_IWUSR 00200 user has write permission
S_IXUSR 00100 user has execute permission
同组用户
S_IRWXG 00070 group has read, write and execute permission
S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IXGRP 00010 group has execute permission
其他组
S_IRWXO 00007 others have read, write and execute permission
S_IROTH 00004 others have read permission
S_IWOTH 00002 others have write permission
S_IXOTH 00001 others have execute permission
1.2 错误码---》在linux中定义一个int类型的全局变量叫errno, 保存的是所有错误对应的编号
补充:find / -name errno.h(在根目录下面寻找一个名字叫做errno.h文件)
我们的前辈将所有文件IO中产生的错误全部罗列,采用宏定义表述错误
头文件:/usr/include/asm-generic/errno.h
perror()--->帮助我们将错误的原因打印出来
头文件:#include
void perror(const char *s);//参数为字符串
1.3文件的读写 read() write()
头文件:#include
函数原型:
ssize_t read(int fd, void *buf, size_t count);
返回值:成功 返回成功读取的字节数
失败 返回 -1
0 文件读完了
函数参数:int fd -----》你要读取的文件的描述符
void *buf -----》储存你读取的内容
size_t count -----》你打算读取多少个字节的数据
头文件:#include
函数原型:
ssize_t write(int fd, const void *buf, size_t count);
返回值:成功 返回成功写入的字节数
失败 返回 -1
0 文件写完了
函数参数:int fd -----》你要写入的文件的描述符
const void *buf -----》储存你写入的内容
size_t count -----》你打算写入多少个字节的数据
清空写入的操作:bzero
头文件:#include
函数原型:
void bzero(void *s, size_t n);
参数:void *s -----》你要清空的对象
size_t n -----》你要清空的空间大小
1.4文件的关闭 close()
#include
int close(int fd);
返回值:成功 返回 0
失败 返回 -1
参数:int fd ---》你打算关闭的文件描述符
/*
打开文件且只读
*/
#include "myhead.h"
int main(void)
{
int fd;//文件描述符
//打开文件,打开当前路径下已经存在文件
fd=open("./2.txt",O_RDONLY);
if(fd == -1)
{
printf("open 1.txt false!
");
return -1;//条件有问题异常退出
}
return 0;
}
/*
创建文件并打开
*/
#include "myhead.h"
int main(void)
{
int fd;//文件描述符
//打开并创建文件,在当前路径下创建文件
fd=open("./2.txt",O_CREAT | O_TRUNC |O_RDWR);
if(fd == -1)
{
printf("open 1.txt false!
");
return -1;//条件有问题异常退出
}
return 0;
}
/*
创建一个文件并且赋权限
*/
#include "myhead.h"
int main(void)
{
int fd;//文件描述符
//创建一个3.txt并且将权限改为666
//fd=open("./3.txt",O_CREAT | O_TRUNC ,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);//啰嗦写法
fd=open("./3.txt",O_CREAT | O_TRUNC |O_RDWR,0666);
if(fd == -1)
{
printf("create 3.txt false!
");
return -1;//条件有问题异常退出
}
return 0;
}
/*
perror错误打印
*/
#include "myhead.h"
int main(void)
{
int fd;//文件描述符
//打开当前目录下已经存在1.txt,但是1.txt文件权限为只读,我想让它可读可写(矛盾)
fd=open("./1.txt",O_RDWR);
if(fd == -1)
{
printf("create 3.txt false!,errno is %d
",errno);
perror("create 3.txt false!");
return -1;//条件有问题异常退出
}
return 0;
}
/*
拷贝文件1的内容到文件2
实现 ./my_cp 1.txt 2.txt
判断下参数个数
*/
#include
#include
#include
#include
#include
int main(int argc, char const *argv[])
{
int fd1,fd2;
char buf[50];
char buf1[50];
bzero(buf,50);
bzero(buf1,50);
fd1=open(argv[1],O_RDWR);
fd2=open(argv[2],O_RDWR);
if(fd1==-1||fd2==-1)
{
perror("open false!
");
return -1;
}
printf("argc:%d
",argc);
read(fd1,buf,50);
write(fd2,buf,50);
close(fd1);
close(fd2);
fd1=open(argv[1],O_RDWR);
fd2=open(argv[2],O_RDWR);
read(fd1,buf,50);
read(fd2,buf1,50);
printf("1.txt:%s
",buf1);
printf("2.txt:%s
",buf1);
close(fd1);
close(fd2);
}
1.5 设置文件的读写偏移(光标) lseek()
头文件: #include
#include
函数原型:
off_t lseek(int fd, off_t offset, int whence);
返回值:成功 返回文件当前位置距离文件开头的字节数
失败 返回 -1
函数参数:int fd ----》你要设置读写偏移的那个文件的文件描述符
off_t offset ----》你打算偏移多少个字节
int whence ----》你打算偏移位置
SEEK_SET 文件的开头
SEEK_CUR 当前的位置
SEEK_END 文件的末尾
lseek(fd,-2,SEEK_SET);//不起作用,还是停留在起始位置
lseek(fd,2,SEEK_SET);//从开头往后挪动2个字节
lseek(fd,-2,SEEK_CUR);//从当前位置往前挪动2个字节
lseek(fd,2,SEEK_CUR);//从当前位置往后挪动2个字节
lseek(fd,-2,SEEK_END);//从末尾位置往前挪动2个字节
lseek(fd,2,SEEK_END);//从末尾位置往后挪动2个字节
off_t ret=lseek(fd,0,SEEK_END); //返回值就表示文件大小
#include "myhead.h"
int main(void)
{
int fd;//文件描述符
int ret1,ret2;
char buf[50];
char buf1[]="helloworld";
bzero(buf,50);
//打开你要读写的文件
fd=open("./2.txt",O_RDWR);
if(fd == -1)
{
perror("open 1.txt flase!
");//打印错误提示
return -1;//异常退出
}
//给文件写入数据
ret2=write(fd,buf1,sizeof(buf1));
if(ret2 == -1)
{
perror("写失败
");
return -1;
}
lseek(fd,0,SEEK_SET);
close(fd);
fd=open("./2.txt",O_RDWR);
//while(1)
//{
ret1=read(fd,buf,10);
/* if(ret1 ==0)//说明文件读完
break; */
//}
printf("我读取到的内容是%s
",buf);
close(fd);
return 0;
}
1.6获取文件属性 stat() man 3 stat
文件的属性:大小,文件类型,名称,日期,所有者,权限
头文件:#include
函数原型:
int stat(const char *restrict path, struct stat *restrict buf);
返回值: 成功 返回 0
失败 返回 -1
函数参数:const char *restrict path----》文件的路径
struct stat *restrict buf----》存放你获取到的文件属性
struct stat
{
dev_t st_dev; /* 设备文件的编号 */
ino_t st_ino; /* 节点编号 */
mode_t st_mode; /* 文件的权限*/
nlink_t st_nlink; /* 硬链接数*/
uid_t st_uid; /* 用户组ID*/
gid_t st_gid; /* 同组用户ID*/
dev_t st_rdev; /* 设备ID (if special file) */
off_t st_size; /* 文件大小,文件字节*/
blksize_t st_blksize; /* 块设备文件大小 */
blkcnt_t st_blocks; /* 512B块设备大小 */
time_t st_atime; /* 上次访问时间 */
time_t st_mtime; /* 上次修改时间 */
time_t st_ctime; /* 上次状态改变时间*/
};
访问头文件路径:/usr/include/linux/stat.h
用于判断文件类型的宏定义
判断是否为链接文件
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
判断是否为普通文件
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
判断是否为目录文件
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
判断是否为字符块设备文件
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
判断是否为块设备文件
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
判断是否为管道文件
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
判断是否为套接字文件
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
用户
#define S_IRWXU 00700
#define S_IRUSR 00400
#define S_IWUSR 00200
#define S_IXUSR 00100
同组
#define S_IRWXG 00070
#define S_IRGRP 00040
#define S_IWGRP 00020
#define S_IXGRP 00010
其他
#define S_IRWXO 00007
#define S_IROTH 00004
#define S_IWOTH 00002
#define S_IXOTH 00001
/*
文件属性
*/
#include "myhead.h"
int main(void)
{
int ret;
struct stat mystat;
//获取当前路径下1.txt文件属性
ret=stat("1.txt",&mystat);
if(ret == -1)
{
perror("get file stat failed!
");
return -1;
}
//打印文件属性
printf("文件的大小:%ld
",mystat.st_size);
printf("文件的权限:%o
",mystat.st_mode);
//判断文件类型
if(S_ISREG(mystat.st_mode))
{
printf("1.txt 普通文件
");
}
if(S_ISDIR(mystat.st_mode))
{
printf("1.txt 目录文件
");
}
//判断文件权限
if(((mystat.st_mode) & S_IFMT) == S_IRUSR)
{
printf("当前用户对于1.txt来说是可读的
");
}
if(((mystat.st_mode) & S_IFMT) == S_IWUSR)
{
printf("当前用户对于1.txt来说是可写的
");
}
if(((mystat.st_mode) & S_IFMT) == S_IXUSR)
{
printf("当前用户对于1.txt来说是可执行
");
}
return 0;
}
/*
文件权限
*/
#include "myhead.h"
int main(void)
{
int ret;
struct stat mystat;
//获取当前路径下1.txt文件属性
ret=stat("1.txt",&mystat);
if(ret == -1)
{
perror("get file stat failed!
");
return -1;
}
//打印文件属性
printf("文件的大小:%ld
",mystat.st_size);
printf("文件的权限:%o
",mystat.st_mode);
//判断文件类型
if(S_ISREG(mystat.st_mode))
{
printf("1.txt 普通文件
");
}
if(S_ISDIR(mystat.st_mode))
{
printf("1.txt 目录文件
");
}
//判断文件权限
if((mystat.st_mode) & S_IRUSR)
{
printf("当前用户对于1.txt来说是可读的
");
}
if((mystat.st_mode) & S_IWUSR)
{
printf("当前用户对于1.txt来说是可写的
");
}
if((mystat.st_mode) & S_IXUSR)
{
printf("当前用户对于1.txt来说是可执行
");
}
return 0;
}
1.7文件的重定向
命令重定向: ls -l> 1.txt 将标准输出重定向到1.txt
linux系统将标准输入 标准输出 标准错误输出定义成了3个宏
0 1 2
STDIN_FILENO STDOUT_FILENO STDERR_FILENO
linux函数重定向:dup()和dup2()
#include
int dup(int oldfd);//给文件描述符换一个新的数字
返回值:成功 返回 新的文件描述符
失败 返回 -1
参数:int oldfd----》旧的文件描述符
结论:新的文件描述符和旧的文件描述符都是指向同一个文件,都可以使用
int dup2(int oldfd, int newfd);
返回值:成功 返回 新的文件描述符
失败 返回 -1
参数:int oldfd 旧的文件描述符
int newfd 新的文件描述符
总结一下: 1.txt---->fd
2.txt---->fd1
dup2(fd,fd1);//fd1跟2.txt已经无关了,跟1.txt有关系了
/*
dup()
*/
#include "myhead.h"
int main(void)
{
int fd;
int newfd;
//打开文件1.txt
fd=open("1.txt",O_RDWR);
if(fd == -1)
{
perror("open 1.txt fales
");
return -1;
}
printf("1.txt is %d
",fd);
//使用重定向函数,给1.txt重新分配新的文件描述符
newfd=dup(fd);
printf("newfd is %d
",newfd);
//往1.txt里面写内容
write(fd,"hello",5);
write(newfd,"world",5);
return 0;
}
/*
dup2()
*/
#include "myhead.h"
int main(void)
{
int fd,fd1;
int newfd;
//打开文件1.txt
fd=open("1.txt",O_RDWR);
if(fd == -1)
{
perror("open 1.txt fales
");
return -1;
}
//打开文件2.txt
fd1=open("2.txt",O_RDWR);
if(fd == -1)
{
perror("open 2.txt fales
");
return -1;
}
printf("1.txt is %d
",fd);
//使用重定向函数,给1.txt重新分配新的文件描述符
/* newfd=dup2(fd,15);
dup2(fd,1); */
dup2(fd,fd1);
//printf("newfd is %d
",newfd);
//往1.txt里面写内容
write(fd1,"hello",5);
//write(newfd,"world",5);
return 0;
}
/*
dup2文件描述符改向
*/
#include "myhead.h"
int main(void)
{
int fd,fd1;
int newfd;
//打开文件1.txt
fd=open("1.txt",O_RDWR);
if(fd == -1)
{
perror("open 1.txt fales
");
return -1;
}
//打开文件2.txt
fd1=open("2.txt",O_RDWR);
if(fd == -1)
{
perror("open 2.txt fales
");
return -1;
}
printf("1.txt is %d
",fd);
//使用重定向函数,给1.txt重新分配新的文件描述符
newfd=dup2(fd,fd1);
dup2(fd,fd1);//现在状态就表明两个文件描述符都会指向同一个地方,由前面fd决定
printf("newfd is %d
",newfd);
//往1.txt里面写内容
write(fd1,"hello",5);
return 0;
}
/*
dup2随便指定15为文件描述符
*/
#include "myhead.h"
int main(void)
{
int fd;
int newfd;
//打开文件1.txt
fd=open("1.txt",O_RDWR);
if(fd == -1)
{
perror("open 1.txt fales
");
return -1;
}
printf("1.txt is %d
",fd);
//使用dup2重新分配新的文件描述符
newfd=dup2(fd,15);//分配新的文件描述符15
printf("newfd is %d
",newfd);
//往1.txt里面写内容
write(newfd,"hello",5);//向15里面写入内容相当向1.txt里面写内容
return 0;
}
fopen() fread() fwrite() fclose() fstat() fseek() ftell() rewind()
fprintf() fscanf() sprintf() sscanf() ferror() feof()
fputs() fgets() fputc() fgetc() puts() gets() putchar() getchar()
1.文件的打开 fopen()
头文件:#include
函数原型:
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
函数原型
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
函数原型:
int fclose(FILE *fp);
返回值: 成功 返回0
失败 返回feof()监测
函数参数:FILE *fp 文件描述符
总结:
(1)open那一组函数和fopen这一组函数之间区别
区别一:open这一组, 对文件描述符进行操作
fopen这一组,对FILE *进行操作
区别二:open这一组 不带缓冲区
fopen这一组 带缓冲区
4.判断文件的结束标志 feof()
头文件:#include
函数原型:
int feof(FILE *stream);
返回值: 不等于0 ---》文件读取完毕
等于0 ---》文件没有读取完毕
#include "myhead.h"
int main()
{
char buf[50];
bzero(buf,50);
//打开源文件
FILE *filep1=fopen("1.txt","r+");
if(filep1 == NULL)
{
perror("fopen filep1 false!
");
return -1;
}
//打开目标文件
FILE *filep2=fopen("2.txt","w+");
if(filep2 == NULL)
{
perror("fopen filep1 false!
");
return -1;
}
//拷贝
while(1)
{
//读取源文件
fread(buf,1,1,filep1);
if(feof(filep1)!= 0)//表明文件读取完毕
break;
fwrite(buf,1,1,filep2);
}
//关闭文件
fclose(filep1);
fclose(filep2);
}
5.设置文件的读写偏移 man 3
#include
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
int fstat(int fildes, struct stat *buf);
返回值:成功 返回0
失败 返回-1
参数:int fildes 你要获取属性的那个文件的文件描述符
struct stat *buf 存放你获取到的文件属性
7.fprintf() fscanf() sprintf() sscanf()
标准输入 stdin
标准输出 stdout
标准错误输出 stderr
可变参的函数(变参函数)
#include
7.1 int fprintf(FILE *stream, const char *format, ...);
参数:FILE *stream FILE * 文件名
const char *format 字符串
...
例子:fprintf(filep,"hello%s%d%.2f
",buf,year,d);
//文件内容拼接
/*
fprintf()的使用
*/
#include "myhead.h"
int main()
{
char buf[]="world";
int year=2018;
float d=5.20;
FILE *filep=fopen("1.txt","w+");
if(filep == NULL)
{
perror("filep false
");
return -1;
}
fprintf(filep,"hello%s%d%.2f
",buf,year,d);//拼接
fprintf(stdout,"%s
",buf);//证明可以通过标准输出把内容显示到屏幕上
//等同于printf("%s
",buf);
}
7.2 int sprintf(char *str, const char *format, ...);
//按照你指定的格式拼接字符串,比strcat要厉害
参数:char *str 字符串拼接指定位置
const char *format 字符串格式
...
例子:sprintf(buf0,"%sworld-%d-%d-%d",buf,year,month,day);
#include "myhead.h"
int main()
{
char buf0[100];
char buf[]="hello";
int year=2018;
int month=7;
int day=8;
float a=12.5;
sprintf(buf0,"%sworld-%d-%d-%d",buf,year,month,day);
printf("%s
",buf0);
return 0;
}
7.3 int fscanf(FILE *stream, const char *format, ...);
参数:FILE *stream FILE * 文件名
const char *format 字符串
...
往文件里面添加内容
#include "myhead.h"
int main()
{
char buf[100];
bzero(buf,100);
FILE *filep=fopen("1.txt","r+");
if(filep == NULL)
{
perror("filep false
");
return -1;
}
fscanf(stdin,"%s",buf);
fprintf(stdout,"%s",buf);
return 0;
}
7.4 int sscanf(const char *str, const char *format, ...);
//按照你指定的格式拆分字符串
参数:char *str 字符串拆分指定位置
const char *format 字符串格式
...
例子:sscanf(time,"%d-%d-%d",&year,&month,&day);//访问的是地址 &
#include "myhead.h"
int main()
{
char time[]="2018-12-1 16:00:30 MON";
int year,month,day;
sscanf(time,"%d-%d-%d",&year,&month,&day);//访问的是地址 &
printf("year %d month %d day %d
",year,month,day);
return 0;
}
8.fputs() fgets() fputc() fgetc() puts() gets() putchar() getchar()
#include
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()!='
')
char *gets(char *s); gets(buf);
//默认获取键盘输入的字符串
#include
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);
/*
使用fputs和fgets实现文件拷贝
*/
#include "myhead.h"
int main(void)
{
int ret;
char buf[100];
//打开源文件
FILE *myfile1=fopen("1.txt","r+");
if(myfile1 == NULL)
{
fputs("myfile create failed!
",stdout);
return -1;
}
//打开文件拷贝的位置
FILE *myfile2=fopen("2.txt","w+");
if(myfile2 == NULL)
{
fputs("myfile create failed!
",stdout);
return -1;
}
//拷贝
while(1)
{
bzero(buf,100);
//读取文件里面的内容
fgets(buf,100,myfile1);
if(feof(myfile1)!=0)
break;
//写数据到文件
fputs(buf,myfile2);
}
//关闭文件
fclose(myfile1);
fclose(myfile2);
return 0;
}
1.相关的接口函数
1.1目录的打开 opendir()
头文件#include
#include
函数原型:
DIR *opendir(const char *name);
返回值:成功 返回DIR类型的指针指向你打开的目录
失败 返回NULL
参数:const char *name 完整的目录路径
1.2 目录的读取 readdir()
#include
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
函数原型:
int mkdir(const char *path, mode_t mode);
参数:const char *path ----》你要建立的目录的路径
mode_t mode ----》新建文件的权限 0777
1.4关闭目录 closedir()
#include
#include
int closedir(DIR *dirp);//结构体指针
以树形方式去查看目录中的内容 tree 目录名
总结:就是学习使用一些系统提供的接口函数
系统IO --->标准IO--->目录操作
//mytree实现 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#include
#include
#include
#include
#include
#include
#include
void mytree(const char *path)
{
int i;
static int flag=0;
char dirpath[1024];
struct dirent *mydirent;
DIR *mydir=opendir(path);
if(mydir==NULL)
{
perror("opendir false!
");
exit(1);
}
while((mydirent = readdir(mydir)) != NULL)
{
if(!strcmp(mydirent->d_name,".")||!strcmp(mydirent->d_name,".."))
continue;
for(i = 0; i < flag; i++)
{
printf("|");
printf(" ");
}
printf("|___ ");
printf("%s
", mydirent->d_name);
if(mydirent->d_type == DT_DIR)
{
sprintf(dirpath,"%s/%s",path,mydirent->d_name);
flag++;
mytree(dirpath);
flag--;//因为调用的时候又运行一次falg++
}
}
closedir(mydir);
}
int main(int argc , char *argv[])
{
printf("%s
",argv[1]);
mytree(argv[1]);
return 0;
}