一、底层文件访问方式
(一)文件描述符
0:标准输入
1:标准输出
2:标准错误
(二)write系统调用
1、系统原型
#include<unistd.h>
size_t write(int fildes,const void *buf,size_t nbytes);
2、示例程序
#include <unistd.h>
#include <stdio.h>
int main()
{
if((write(1,"Here is some data\n",18))!=18)
write(2,"A write error has occurred on file descriptor 1\n",46);
exit(0);
}
3、输出
Here is some data
(三)read系统调用
1、系统原型
#include<unistd.h>
size_t read(int fildes,void *buf,size_t nbytes);
2、示例程序
#include <unistd.h>
#include <stdlib.h>
int main(){
char buffer[128];
int nread;
nread = read(0,buffer,128);
if(nread==-1)
write(2,"A read error has occurred\n",26);
if((write(1,buffer,nread))!=nread)
write(2,"A write errot has occurred\n",27);
exit(0);
}
3、输出
$echo hello world | ./3.4.2_simple_read
hello world
(四)open系统调用
1、系统原型
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
int open(const char *path,int oflags);
int open(conat char *path,int oflags,mode_t mode);
2、oflags的类型
O_RDONLY 以只读方式打开
O_WRONLY 以只写方式打开
O_RDWR 以读写方式打开
O_APPEND 将写入的数据追加在文件的末尾
O_TRUNC 将文件长度设置为0,丢弃已有的内容
O_CREAT 如果需要,按照mode给出的参数创建文件
O_EXCL 与O_CREAT一起使用,确保调用者创建出文件
前三个必须要选择一个,且仅一个,后面的类型与选中的通过“|”运算符配合使用
3、mode访问权限初始值
S_IRUSR 读权限,文件属主
S_IWUSR 写权限,文件属主
S_IXUSR 执行权限,文件属主
S_IRGRP 读权限,文件所属组
S_IWGRP 写权限,文件所属组
S_IXGRP 执行权限,文件所属组
S_IROTH 读权限,其他用户
S_IWOTH 写权限,其他用户
S_IXOTH 执行权限,其他用户
(五)close系统调用
1、系统原型
#include <unistd.h>
int close(int fildes);
(六)示例程序
1、文件复制程序
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
char block[100];
int in,out;
int nread;
in = open("file.in",O_RDONLY);
out = open("file.out",O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR);
while((nread= read(in,block,sizeof(block)))>0)
write(out,block,nread);
exit(0);
}
2、输出
TIMEFOMAT="" time ./copy_block
0.00user 0.00system 0:00.00elapsed 66%CPU
二、标准I/O库
(一)fopen函数
1、函数原型
#include <stdio.h>
FILE *fopen(const char *filename,const char *mode);
2、mode取值
"r"或"rb" 以只读方式打开
"w"或"wb" 以写方式打开,并使文件长度为0
"a"或"ab" 以写方式打开,新内容追加在文件尾部
"r+"或"rb+"或"r+b" 以更新方式打开(读和写)
"w+"或"wb+"或"w+b" 以更新方式打开,并使文件长度为0
"a+"或"ab+"或"a+b" 以更新方式打开,新内容追加在文件尾
(二)fread,fwrite,fclose,fflush,fseek,fgetc,getc,getchar,fputc,putc,putchar,fgets,gets函数
1、函数原型
#include <stdio.h>
size_t fread(void *ptr,size_t size,size_t nitems,FILE *stream);//nitems给出了要传输的记录的个数
size_t fwrite(void *ptr,size_t size,size_t nitems,FILE *stream);//nitems给出了要传输的记录的个数
int fclose(FILE *stream);//关闭指定的文件流,隐含执行一次fflush
int fflush(FILE *stream);//将文件流里所有未写出的数据都写出,无需在fclose之前调用
int fseek(FILE *stream,long int offset,int whence);//指定下一次读写操作的位置;返回0表示成功,-1表示失败
int fgetc(FILE *stream);
int getc(FILE *stream);
int getchar();
int fputc(FILE *stream);
int putc(FILE *stream);
int putchar();
char *fgets(char *s,int n,FILE *stream);//每次调用最多传输n-1个字符,最后一个字符用于存放‘\0’.
char *gets(char *s);//读取数据并丢弃遇到的换行符
2、示例程序
#include<stdio.h>
#include <stdlib.h>
int main()
{
int c;
FILE *in,*out;
in = fopen("file.in","r");
out = fopen("file.out","w");
while((c= fgetc(in))!=EOF)
fputc(c,out);
exit(0);
}
3、输出
TIMEFOMAT="" time ./copy_stdio
0.00user 0.00system 0:00.00elapsed 75%CPU
三、文件和目录维护函数
1、各个函数原型
#include <sys/stat.h>
int chmod(const char *path,mode_t mode);//改变文件或是目录的访问权限。mode参数与open系统调用一样
#include<sys/types.h>
#include <unistd.h>
int chown(const char *path,uid_t owenergid_t group);//改变文件的属主
#include <unistd.h>
int unlink(const char *path);
int link(const char *path1,const char *path2);
int symlink(const char *path1,const char *path2);//创建符号链接,符号链接不会增加文件的连接数。
#include <sys/types.h>
#include <sys/stat.h>
int mkdir(const char *path,mode_t mode);
#include <unistd.h>
int rmdir(const char *path);
#include <unistd.h>
int chdir(const char *path);//切换到当前目录
#include <unistd.h>
char *getcwd(char *buf,size_t size);//获取当前目录到buf中
四、扫描目录函数
1、函数原型
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);//打开一个目录
struct dirent *readdir(DIR *dirp);//返回一个保存着目录流dirp中下一个目录项有关资料的指针
long int telldir(DIR *dirp);//返回目录流的当前位置
void seekdir(DIR *dirp,long int loc);//设置目录流dirp的目录项指针
int closedir(DIR *dirp);
其中,dirent结构中包含目录项内容如下:
ino_t d_nio:文件的inode节点号
char d_name[]:文件的名字
2、程序示例(一个目录扫描程序)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
void printdir(char *dir,int depth)//输出当前目录的内容,depth用来控制缩排
{
DIR *dp;
struct dirent *entry;
struct stat statbuf;
if((dp = opendir(dir))==NULL){//检查指定目录是否存在
fprintf(stderr,"cannot open directory: %s\n",dir);
return ;
}
chdir(dir);//进入指定目录
while((entry=readdir(dp))!=NULL){//检查该数据项是否是一个目录
lstat(entry->d_name,&statbuf);
if(S_ISDIR(statbuf.st_mode)){
if(strcmp(".",entry->d_name)==0
||strcmp("..",entry->d_name)==0)
continue;
printf("%*s%s/\n",depth,"",entry->d_name);
printdir(entry->d_name,depth+4);
}
else printf("%*s%s\n",depth,"",entry->d_name);
}
chdir("..");//返回上一级目录
closedir(dp);
}
int main(int argc, char* argv[]){
char *topdir = ".";
if(argc>=2)
topdir = argv[1];
printf("Directory scan of %s:\n",topdir);
printdir("/home",0);
printf("done.\n");
exit(0);
}
3、输出
./3.8.5_printdir /home | more
Directory scan of /home:
xxxxxxx/
.mozilla/
extensions/
{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/
plugins/
firefox/
7j5tb4bn.default/
times.json
.parentlock
.............
.esd_auth
.bash_history
.viminfo
done.