Linux系统编程-文件操作

列出常用文件操作的系统函数与c库函数,在这里做笔记备忘,更多函数可用man命令查询并学习。

参考资料:

《linux系统编程》,《Unix/Linux系统编程实践》
http://blog.csdn.net/zjf280441589/article/details/43875987
http://akaedu.github.io/book/ch28s02.html

Linux的设计哲学: 一切皆文件所有的文件或设备都对应一个文件描述符,包括输入输出都是写入到文件中,可见文件操作的重要性啊

文件类型:

- 文件
d 目录
l 符号链接

伪文件(不占用磁盘空间):

s 套接字
b 块设备
c 字符设备
c 管道

1.一个进程启动时, 默认已经打开了3个文件, 标准输入(0, STDIN_FILENO), 标准输出(1, STDOUT_FILENO), 标准错误输出(2, STDERR_FILENO), 这些常量定义在unistd.h头文件中; 其中, 文件描述符基本上是与文件描述指针一一对应的, 如文件描述符0,1,2 对应 stdin, stdout, stderr;
2.文件描述符与文件指针的转换
fileno: 将文件指针转换成文件描述符
int fileno(FILE stream);
fdopen: 将文件描述符转换成文件指针
FILE
fdopen(int fd, const char *mode);

系统函数:

## 文件操作:

open()

打开文件,返回文件描述符

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…)
mode: 用来指定对文件所有者, 文件用户组以及系统中的其他用户的访问权限;

close()

释放文件描述符,与open写在一起别忘了关文件

int close(int fd);

### read()

读取一个文件内容到buffer

ssize_t read(int fd, void *buffer, size_t count);

write()

写入buffer内容到内核缓冲区,不会真正的写入,必须要输入缓冲区猜,
有三种情况:1.调用fsync()函数,立即刷入 ( int fsync(int fd))
      2.close文件
      3. 缓冲区满

ssize_t write(int fd, const void *buf, size_t count);  

lseek()

文件的随机读写

off_t lseek(int fd, off_t offset, int whence);

参数:whence:SEEK_SET(文件开头),SEEK_CUR(当前位置),SEEK_END(文件结尾)
   offset:相对于whence的偏移量
返回值:新的文件偏移值

stat()

获取文件信息到buf的stat结构体里面,可以使用stat命令打印一个文件stat结构体内的信息(inode中的信息,不过inode是内核层的),这里涉及到文件的信息存储,可以看前面的一篇文章。

int stat(FAR const char *path, FAR struct stat *buf)  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct stat  
{
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
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 */
};

dup,dup2()

复制文件描述符,返回的是未被占用的编号最小的文件描述符号

dup2(old,new);//dup2(2,3);2复制到3,3也就和2一样指向了stderror;

fcntl():

改变已经打开文件的属性,可读可写等
int fcntl (int fd,int cmd);
int fcntl (int fd,int cmd,long arg);
int fcntl (int fd,int cmd,struct flock* lock);

ftruncate()与truncate()

改变文件大小

举例:

仿写cp命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#define COPYMODE 0644
#define BUFFERSIZE 4096
int cp(int ac,char * av[])
{
int in_fd,out_fd;
char *buffer=new char(BUFFERSIZE);
if((in_fd=open(av[1],O_RDONLY))==-1){
cout<<"open false"<<endl;//oops("cannot open",av[1]);
return -1;
}

if((out_fd=creat(av[2],COPYMODE))==-1){
cout<<"create file false"<<endl;
return -1;
}

int size;
int count=0;
while((size=read(in_fd,buffer,BUFFERSIZE))>0)
{

count++;
if(write(out_fd,buffer,size)!=size){
cout<<"write error"<<endl;
return -1;
}
}
if(size==-1){
cout<<"read error"<<endl;
return -1;
}

if(close(in_fd)==-1||close(out_fd)==-1){
cout<<"error"<<endl;
return -1;
}
}


目录操作

opendir()

打开目录,返回目录指针

DIR *opendir(const char *name);

chdir()

修改当前进程的路径

getcwd()

获取当前进程工作目录

mkdir()

创建目录

int mkdir(const char *pathname, mode_t mode);  

rmdir()

删除一个空目录

int rmdir(const char *pathname);

readdir()

读目录,返回一个dirent结构(dentry)

struct dirent *readdir(DIR *dirp);

返回:返回一个指向dirent结构的指针,dierent结构可以参见上一篇

closedir()

关闭目录

int closedir(DIR *dirp); 

Chmod, fchmod

更改目录权限

int chmod(const char *path, mode_t mode);  
int fchmod(int fd, mode_t mode);  

### chown,fchown

更改文件所有者/所属组

int chown(const char *path, uid_t owner, gid_t group);  
int fchown(int fd, uid_t owner, gid_t group);  

举例0

递归获取普通目录下文件的个数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
int get_file_count(char* root)
{
//打开文件
DIR* dir=NULL;
dir=opendir(root);
if(dir==NULL)
{
perror("error");
exit(1);
}
struct dirent* ptr =NULL;
char path[1024]={0};
int total=0;
while((ptr=readdir(dir))!=NULL)
{
//过滤. 和..
if(strcmp(ptr->d_name,".")==0||strcmp(ptr->d_name,"..")==0)
{
continue;
}
if(ptr->d_type==DT_DIR)
{
//转换路径并递归调用
sprintf(path,"%s/%s",root,ptr->d_name);
total+=get_file_count(path);
}
if(ptr->d_type==DT_REG)
{
total++;
}
}
closedir(dir);
return total;
}

链接

删除临时文件目录项,使之具备被释放的条件

c库函数

rename()

重命名文件

本文标题:Linux系统编程-文件操作

文章作者:Hengliy

发布时间:2018年01月12日 - 10:01

最后更新:2018年02月24日 - 01:02

原始链接:http://hengliy.github.io/2018/01/12/LINUX系统编程-文件操作/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。