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);
参数:
char *pathname:文件路径+文件名;
int flags:文件的打开方式。
O_RDONLY 只读
O_WRONLY 只写
O_RDWR 读写
----以上三种必须包含一种-----
O_APPEND 追加
O_CREAT 创建
O_TRUNC 清空
“w”: O_WRONLY|O_CREAT|O_TRUNC //以写的方式打开目标文件,如果目标文件不存在则创建,如果存在则清空;
mode_t mode:文件的八进制权限,0777、0664 ;
如果 flags 包含了 O_CREAT;必须要有mode参数,否则会忽略O_CREAT;
返回值:
成功,返回文件描述符;
失败,返回-1,更新errno;
例程:
int fd = open("./2.png", O_WRONLY|O_CREAT|O_TRUNC, 0664);
if(fd < 0)
{
perror("open");
fprintf(stderr, "%d\n", __LINE__);
return -1;
}
close
关闭一个文件
头文件:
#include <unistd.h>
原型:
int close(int fd);
参数:
int fd:指定要关闭的文件描述符;
返回值:
成功,返回0;
失败,返回-1,更新errno;
例程:
close(fd);
write
将数据写入到文件中
头文件:
#include <unistd.h>
原型:
ssize_t write(int fd, const void *buf, size_t count);
参数:
int fd:文件描述符;
void *buf:存储着要写入到文件中的数据的首地址,可以是任意类型;
size_t count:要写入的数据大小,以字节为单位;
返回值:
成功,返回写入的数据个数;
失败,返回-1,更新errno;
例程:
char buf[N] = "hello world";
if(write(fd,buf,strlen(buf)) < 0)
{
perror("write");
return -1;
}
read
从文件中读取数据
头文件:
#include <unistd.h>
原型:
ssize_t read(int fd, void *buf, size_t count);
参数:
int fd:文件描述符;
void *buf:存储读取到的数据,可以是任意类型;
size_t count:要读取的数据大小,以字节为单位;
返回值:
成功,返回读取到的数据个数;
0,表示读取到文件结尾;
失败,返回-1,更新errno;
例程:
int fd = open("./open.txt", O_RDONLY);
char c = 0;
while(read(fd , &c, 1)!=0)
{
printf("%c",c);
}
lseek
偏移文件指针,并返回设置后的文件指针相对于文件开头的偏移量
头文件:
#include <sys/types.h>
#include <unistd.h>
原型:
off_t lseek(int fd, off_t offset, int whence);
参数:
int fd:文件描述符;
long offset:相对于参数whence的偏移量;
int whence:
SEEK_SET:文件开头位置。
SEEK_CUR:文件当前位置;
SEEK_END:文件结尾位置;
返回值:
成功,返回设置后的文件指针相对于文件开头的偏移量;
失败,返回(off_t)-1,更新errno;
例程:
计算文件大小:
off_t size = lseek(fd, 0, SEEK_END);
相当于:
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
umask
修改文件权限掩码(文件创建的真正权限是mode & ~umask)
头文件:
#include <sys/types.h>
#include <sys/stat.h>
原型:
mode_t umask(mode_t mask);
例程:
umaks(0);//保持文件原有权限
0777 & ~0002
= 111 111 111 & ~000 000 010
= 111 111 111 & 111 111 101
= 111 111 101 --> 0775
应用例程1
要求用read, write拷贝一张图片,例如将2.png拷贝成3.png
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int copy_picture(int fd_src, int fd_dest)
{
//循环读一次写一次
char s[100] = "";
int ret = 0;
while(1)
{
bzero(s, sizeof(s));
ret = read(fd_src, s, 100);
if(ret < 0)
{
perror("read");
return -1;
}
else if(0 == ret)
{
printf("*****文件读取完毕*****\n");
break;
}
printf("%d\n", ret);
if(write(fd_dest, s, ret) < 0)
{
perror("write");
return -2;
}
}
return 0;
}
int main(int argc, const char *argv[])
{
//以读的方式打开原文件
int fd_src = open("./1.png", O_RDONLY);
if(fd_src < 0)
{
perror("open");
fprintf(stderr, "%d\n", __LINE__);
return -1;
}
//以写的方式打开目标文件,如果目标文件不存在创建,如果存在则清空
int fd_dest = open("./2.png", O_WRONLY|O_CREAT|O_TRUNC, 0664);
if(fd_dest < 0)
{
perror("open");
fprintf(stderr, "%d\n", __LINE__);
return -1;
}
//拷贝 read write
copy_picture(fd_src, fd_dest);
//关闭两个文件描述符
close(fd_src);
close(fd_dest);
return 0;
}
stat
获取文件属性
头文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
原型:
int stat(const char *path, struct stat *buf);
参数:
char *path:文件的路径文件名;
struct stat *buf:存储获取到的文件属性;
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */ inode号;
mode_t st_mode; /* protection */ 文件类型+文件权限;
nlink_t st_nlink; /* number of hard links */ 硬链接数;
uid_t st_uid; /* user ID of owner */ 文件所属用户的uid;
gid_t st_gid; /* group ID of owner */ 文件所属用户组的gid;
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */ 文件大小,以字节为单位;
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */ 最后一次被访问的时间;
time_t st_mtime; /* time of last modification */ 最后一次被修改的时间;
time_t st_ctime; /* time of last status change */ 最后一次改变状态的时间;
};
返回值:
成功,返回0;
失败,返回-1,更新errno;
例程:
struct stat buf;
if(stat(argv[1], &buf) < 0)
{
perror("stat");
return -1;
}
提取文件的权限
st_mode:是一个32位无符号的整形变量,其中低9位[0, 8],代表文件的权限;
用 st_mode & 相应的权限
st_mode: 0100664 664 --> 110 110 100 & 100 000 000 --------------------- 100 000 000 ---->0400 说明当前用户有可读权限 ---> r; 664 --> 110 110 100 & 001 000 000 --------------------- 000 000 000
对应权限的宏
S_IRUSR 00400 owner has read permission S_IWUSR 00200 owner has write permission S_IXUSR 00100 owner has execute permission S_IRWXG 00070 mask for group permissions S_IRGRP 00040 group has read permission S_IWGRP 00020 group has write permission S_IXGRP 00010 group has execute permission S_IRWXO 00007 mask for permissions for others (not in group) S_IROTH 00004 others have read permission S_IWOTH 00002 others have write permission S_IXOTH 00001 others have execute permission
例程:
void get_filemode(mode_t mode)
{
int i;
mode_t m;
for(i=8;i>=0;i--)
{
m = mode & 1<<i;
if(m == 0)
{
putchar('-');
continue;
}
switch(i%3)
{
case 0:
putchar('x');
break;
case 1:
putchar('w');
break;
case 2:
putchar('r');
break;
}
}
}
提取文件的类型
7种文件类型:bcd-lsp
功能:通过宏函数来判断
b S_ISBLK(m) block device?
c S_ISCHR(m) character device?
d S_ISDIR(m) directory?
- S_ISREG(m) is it a regular file?
l S_ISLNK(m) symbolic link?
s S_ISSOCK(m) socket?
p S_ISFIFO(m) FIFO (named pipe)?
参数:
m:文件属性结构体struct stat *buf 中的 mode_t st_mode;
返回值:
1,代表是该类型文件;
0,代表不是该类型的文件;
例程:
void getType(mode_t m)
{
if(S_ISREG(m))
putchar('-');
else if(S_ISDIR(m))
putchar('d');
else if(S_ISCHR(m))
putchar('c');
else if(S_ISBLK(m))
putchar('b');
else if(S_ISFIFO(m))
putchar('p');
else if(S_ISLNK(m))
putchar('l');
else if(S_ISSOCK(m))
putchar('s');
}
st_mode:是一个32位无符号的整形变量,其中低16位到低13位[12, 15],代表文件的类型;
宏 S_IFMT 0170000
通过 st_mode & S_IFMT 提取出4bit 后与下列宏比较,如果相等,则是对应类型的文件。
S_IFSOCK---> 0140000 socket
S_IFLNK-----> 0120000 symbolic link
S_IFREG-----> 0100000 regular file
S_IFBLK-----> 0060000 block device
S_IFDIR-----> 0040000 directory
S_IFCHR----> 0020000 character device
S_IFIFO-----> 0010000 FIFO
例程:
void getType(mode_t m)
{
switch (m & S_IFMT) {
case S_IFBLK: printf("b"); break;
case S_IFCHR: printf("c"); break;
case S_IFDIR: printf("d"); break;
case S_IFIFO: printf("p"); break;
case S_IFLNK: printf("l"); break;
case S_IFREG: printf("-"); break;
case S_IFSOCK: printf("s"); break;
default: printf("unknown?\n"); break;
}
}
获取文件所属用户信息
getpwuid
通过 struct stat 结构体中的 uid_t st_uid 成员变量,获取文件所属用户信息
头文件:
#include <sys/types.h>
#include <pwd.h>
原型:
struct passwd *getpwuid(uid_t uid);
参数:
uid_t uid:文件所属用户的id;
返回值:
成功,返回存储文件所属用户信息的结构体 struct passwd * ;
struct passwd {
char *pw_name; /* username */
char *pw_passwd; /* user password */
uid_t pw_uid; /* user ID */
gid_t pw_gid; /* group ID */
char *pw_gecos; /* user information */
char *pw_dir; /* home directory */
char *pw_shell; /* shell program */
};
失败,返回NULL,更新errno;
例程:
//提取文件所属用户的名字
char* getUsrName(char*name, uid_t uid)
{
struct passwd* pwd = NULL;
pwd = getpwuid(uid);
if(NULL == pwd)
{
perror("getpwuid");
return NULL;
}
strcpy(name, pwd->pw_name);
return name;
}
获取文件所属用户组信息
getgrgid
通过 struct stat 结构体中的 gid_t st_gid 成员变量,获取文件所属用户组信息
头文件:
#include <sys/types.h>
#include <grp.h>
原型:
struct group *getgrgid(gid_t gid);
参数:
gid_t gid:文件所属用户组的id;
返回值:
成功,返回存储用户组信息的结构体指针;struct group * ;
struct group {
char *gr_name; /* group name */
char *gr_passwd; /* group password */
gid_t gr_gid; /* group ID */
char **gr_mem; /* group members */
};
失败,返回NULL,更新errno;
例程:
//提取文件所属用户组的名字
char* getGrpName(char* grpName, gid_t gid)
{
struct group* grp = NULL;
grp = getgrgid(gid);
if(NULL == grp)
{
perror("getgrgid");
return NULL;
}
strcpy(grpName, grp->gr_name);
return grpName;
}
应用例程2
读取一个文件的信息,用main函数外部传参的方式。要求输出结果类似如下:-rw-rw-r-- 1 linux root 236 Mar 29 22:02 1_getfileno.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <pwd.h>
#include <time.h>
#include <grp.h>
//提取文件的权限 方法1
#if 0
void getPermission(mode_t mode)
{/*{{{*/
//获取当前用户的权限
if(mode & 0400)
putchar('r');
else
putchar('-');
if(mode & 0200)
putchar('w');
else
putchar('-');
if(mode & 0100)
putchar('x');
else
putchar('-');
/*-----------------*/
//获取组用户的权限
if(mode & 0040)
putchar('r');
else
putchar('-');
if(mode & 0020)
putchar('w');
else
putchar('-');
if(mode & 0010)
putchar('x');
else
putchar('-');
/*-----------------*/
//获取其他用户的权限
if(mode & 0004)
putchar('r');
else
putchar('-');
if(mode & 0002)
putchar('w');
else
putchar('-');
if(mode & 0001)
putchar('x');
else
putchar('-');
putchar(10);
}/*}}}*/
#endif
//提取文件的权限 方法2
void getPermission(mode_t mode)
{
int i = 0;
for(i=8; i>=0; i--)
{
if((mode & (1<<i)) == 0)
{
putchar('-');
continue;
}
switch(i%3)
{
case 2:
putchar('r');
break;
case 1:
putchar('w');
break;
case 0:
putchar('x');
break;
}
}
}
#if 0
//提取文件类型 方法1
void getType(mode_t m)
{/*{{{*/
if(S_ISREG(m))
putchar('-');
else if(S_ISDIR(m))
putchar('d');
else if(S_ISCHR(m))
putchar('c');
else if(S_ISBLK(m))
putchar('b');
else if(S_ISFIFO(m))
putchar('p');
else if(S_ISLNK(m))
putchar('l');
else if(S_ISSOCK(m))
putchar('s');
}/*}}}*/
#endif
//提取文件类型 方法2
void getType(mode_t m)
{
switch (m & S_IFMT) {
case S_IFBLK: printf("b"); break;
case S_IFCHR: printf("c"); break;
case S_IFDIR: printf("d"); break;
case S_IFIFO: printf("p"); break;
case S_IFLNK: printf("l"); break;
case S_IFREG: printf("-"); break;
case S_IFSOCK: printf("s"); break;
default: printf("unknown?\n"); break;
}
}
//提取文件所属用户名
char* getUsrName(char*name, uid_t uid)
{
struct passwd* pwd = NULL;
pwd = getpwuid(uid);
if(NULL == pwd)
{
perror("getpwuid");
return NULL;
}
strcpy(name, pwd->pw_name);
return name;
}
//提取文件所属组用户的名字
char* getGrpName(char* grpName, gid_t gid)
{
struct group* grp = NULL;
grp = getgrgid(gid);
if(NULL == grp)
{
perror("getgrgid");
return NULL;
}
strcpy(grpName, grp->gr_name);
return grpName;
}
int main(int argc, const char *argv[])
{
if(argc < 2)
{
fprintf(stderr, "请输入文件名\n");
return -1;
}
struct stat buf;
if(stat(argv[1], &buf) < 0)
{
perror("stat");
return -1;
}
//文件的inode号
//printf("inode: %lu\n", buf.st_ino);
//文件的类型+权限
getType(buf.st_mode);
getPermission(buf.st_mode);
//printf("mode+types:%o\n", buf.st_mode);
//文件硬连接数
printf(" %d", buf.st_nlink);
//文件所属用户的id,uid
char name[20] = "";
getUsrName(name, buf.st_uid);
printf(" %s", name);
//文件所属组用户的名字
char grpName[20] = "";
getGrpName(grpName, buf.st_gid);
printf(" %s", grpName);
//文件的大小
printf(" %ld", buf.st_size);
//日期
char time[120] = "";
strcpy(time, ctime(&buf.st_ctime));
time[strlen(time)-1] = 0; //删除'\n'字符
printf(" %s", time);
//打印文件名
printf(" %s", argv[1]);
putchar(10);
putchar(10);
return 0;
}
结果
opendir
打开一个目录文件,并返回目录流指针
头文件:
#include <sys/types.h>
#include <dirent.h>
原型:
DIR *opendir(const char *name);
参数:
char *name:目录文件的路径;
返回值:
成功,返回目录流指针;
失败,返回NULL,更新errno;
例程:
DIR* dp = opendir("/home/linux/");
if(NULL == dp)
{
perror("opendir");
return -1;
}
closedir
关闭目录
头文件:
#include <sys/types.h>
#include <dirent.h>
原型:
int closedir(DIR *dirp);
返回值:
成功,返回0;
失败,返回-1,更新errno;
例程:
closedir(dp);
readdir
通过目录流指针读取目录内容
头文件:
#include <dirent.h>
原型:
struct dirent *readdir(DIR *dirp);
参数:
DIR *dirp:目录流指针;
返回值:
成功,返回存储目录信息的结构体;
struct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* not an offset; see NOTES */
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]; /* filename */
};
失败,返回NULL;
例程:
struct dirent *readptr = NULL;
while(1)
{
//读取目录,读取到的结果存在readptr中
readptr = readdir(dp);
if(NULL == readptr)
{
printf("目录读取完毕\n");
break;
}
if(readptr->d_name[0] != '.')
{
printf("%s\n", readptr->d_name); //打印读取到的文件名
}
}
应用例程3
实现打开目录,显示该目录下所有文件的属性,权限...... 类似ls -l
operateDir.c
#include "getFileStat.h"
#include <dirent.h>
int main(int argc, const char *argv[])
{
DIR *dp = opendir(argv[1]);
if(NULL == dp)
{
perror("opendir");
return -1;
}
struct dirent *readptr = NULL;
while(1)
{
readptr = readdir(dp);
if(NULL == readptr)
{
printf("当前目录下文件信息打印完毕\n");
break;
}
struct stat buf;
//获取当前文件路径
char path[100] = "";
sprintf(path,"%s/%s",argv[1],readptr->d_name);
stat(path,&buf);
get_file_stat(buf,readptr->d_name);
}
closedir(dp);
return 0;
}
getFileStat.c
#include "getFileStat.h"
void get_filemode_lspbcd(mode_t mode)
{
mode_t m = mode & S_IFMT;
switch(m)
{
case S_IFSOCK:
putchar('s');
break;
case S_IFLNK:
putchar('l');
break;
case S_IFREG:
putchar('-');
break;
case S_IFBLK:
putchar('b');
break;
case S_IFDIR:
putchar('d');
break;
case S_IFCHR:
putchar('c');
break;
case S_IFIFO:
putchar('p');
}
}
void get_filemode(mode_t mode)
{
int i;
mode_t m;
for(i=8;i>=0;i--)
{
m = mode & 1<<i;
if(m == 0)
{
putchar('-');
continue;
}
switch(i%3)
{
case 0:
putchar('x');
break;
case 1:
putchar('w');
break;
case 2:
putchar('r');
break;
}
}
}
void get_link(nlink_t nlink_t)
{
printf("%-4ld",(long)nlink_t);
}
void get_uid(uid_t uid)
{
struct passwd *pwd = NULL;
if((pwd = getpwuid(uid))!=NULL)
{
printf("%s",pwd->pw_name);
}
}
void get_gid(gid_t gid)
{
struct group *grp = NULL;
if((grp = getgrgid(gid))!=NULL)
{
printf("%s",grp->gr_name);
}
}
void get_size(off_t size)
{
printf("%-10ld",size);
}
void get_time(time_t time)
{
char t[50] = "";
sprintf(t,"%s",(char *)ctime(&time));
t[strlen(t)-1] = '\0';
printf("%s",t);
}
void get_file_stat(struct stat buf,const char *file)
{
get_filemode_lspbcd(buf.st_mode);
get_filemode(buf.st_mode);
putchar(' ');
get_link(buf.st_nlink);
putchar(' ');
get_uid(buf.st_uid);
putchar(' ');
get_gid(buf.st_gid);
putchar(' ');
get_size(buf.st_size);
putchar(' ');
get_time(buf.st_ctime);
putchar(' ');
printf("%s",file);
putchar(10);
}
getFileStat.h
#ifndef __GETFILESTAT_H__
#define __GETFILESTAT_H__
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <string.h>
void get_filemode_lspbcd(mode_t mode);
void get_filemode(mode_t mode);
void get_link(nlink_t nlink_t);
void get_uid(uid_t uid);
void get_gid(gid_t gid);
void get_size(off_t size);
void get_time(time_t time);
void get_file_stat(struct stat buf,const char *file);
#endif
makefile
a.out:operateDir.o getFileStat.o
gcc operateDir.o getFileStat.o -o a.out
operateDir.o:operateDir.c
gcc -c operateDir.c -o operateDir.o
getFileStat.o:getFileStat.c
gcc -c getFileStat.c -o getFileStat.o
.PHONY:clean
clean:
rm *.o a.out
结果
本文链接:https://shengto.top/c/fileIO_routine.html
转载时须注明出处及本声明