1.Linux应用编程——文件

本文深入探讨Linux下的文件I/O操作,包括基本API如open、read、write、close及lseek的使用方法,同时介绍如何通过opendir、readdir进行目录访问,以及如何利用stat获取文件元数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文件I/O

 

文件IO和标准IO的区别:

 

静态库和共享库的区别:

静态库的特点:

共享库的特点:

 

 

文件描述符:

1.对于Linux内核而言所有的文件或设备都对应一个文件描述符(Linux的设计哲学一切皆文件), 这样可以简化系统编程的复杂程度;

2.当打开/创建一个文件的时候内核向进程返回一个文件描述符(是一个非负整数). 后续对文件的操作只需通过该文件描述符即可进行内核记录有关这个打开文件的信息;

3.一个进程启动时默认已经打开了3个文件标准输入(0, STDIN_FILENO), 标准输出(1, STDOUT_FILENO), 标准错误输出(2, STDERR_FILENO), 这些常量定义在unistd.h头文件中

其中文件描述符基本上是与文件描述指针(FILE*)一一对应的如文件描述符0,1,2 对应 stdin, stdout, stderr;

文件指针与文件描述符的转换

fileno: 将文件指针转换成文件描述符

       int fileno(FILE *stream);

fdopen: 将文件描述符转换成文件指针

       FILE *fdopen(int fd, const char *mode);

 

基础API

1.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);

参数说明:

    pathname:需要打开文件的路径(相对路径,绝对路径都行)

    falgs:文件打开的模式(若有O_CREAT存在,则必须追加mode

mode:新建文件的存取权限
flags常用值

 

 

2.read

#include <unistd.h>

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

fd:文件描述符

buf:读取的数据所存储的空间

count:每次读取数据的大小(若为1则每读一字节系统调用一次)

返回值:返回从文件复制到规定缓冲区的字节数,如果返回0,表示已到达文件尾或无可读取的数据,错误返回-1count0也返回0

 

3.write

#include <unistd.h>

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

解释同上

成功:返回成功写入文件的字节数

 

4.close

#include <unistd.h>

int close(int fd);

关闭文件描述符使得文件描述符得以重新利用

实例——拷贝argv[1]文件中的内容到argv[2]

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

int main(int argc, const char *argv[])

{

int fd1=0,fd2=0;

int buf[100];

int len=0,size=0;

if(argc<3)

{

return -1;

}

if((fd1=open(argv[1],O_RDONLY))<0)

{

perror("fail of open");

return -2;

}

if((fd2=open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0664))<0)

{

perror("fail of open");

return -2;

}

len=read(fd1,buf,100);

size=write(fd2,buf,len);

fprintf(stdout,"%d\n",len);

close(fd1);

close(fd2);

return 0;

}

5.lseek

对应于C库函数中的fseek, 通过指定相对于当前位置末尾位置或开始位置的字节数来重定位currp:

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

返回值新的文件偏移值;(若要获取文件长度,可先将文件移动到头,在移动到尾部,取返回值)

offset:偏移量

Whence取值:

SEEK_SET: 文件头

SEEK_CUR:文件当前位置

SEEK_END:文件尾

 

目录访问

6.opendir

       #include <sys/types.h>

       #include <dirent.h>

       DIR *opendir(const char *name);

返回值:

   成功: 返回目录指针;(作为readdir的输入

   失败: 返回NULL;

 

7.readdir

struct dirent *readdir(DIR *dirp);

返回值:

   成功返回一个指向dirent结构的指针它包含指定目录的下一个连接的细节;

   没有更多连接时返回0;

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 */

};

 

8.closedir: 关闭目录   

int closedir(DIR *dirp);

 

9.stat

功能:获取文件元数据

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

int stat(const char *path, struct stat *buf);

int fstat(int fd, struct stat *buf);

int lstat(const char *path, struct stat *buf);


stat结构体

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 */

};

实例:利用statopendirreaddir实现ls -l

#include <stdio.h>

#include <unistd.h>

#include <sys/types.h>

#include <dirent.h>

#include <grp.h>

#include <sys/types.h>

#include <pwd.h>

#include <sys/stat.h>

#include <time.h>

#include <string.h>

#include <stdlib.h>

 

int ss(char *argv,char *name)

{

struct stat st;//这里需要注意,若定义指针,不开辟空间会导致野指针的问题,固这里直接定义结构体,函数调用时直接用区地址符。

int i=0;

char *time=NULL;

if(stat(argv,&st) != 0)//stat得到文件爱女的详细信息,并存入st结构体

{

perror("fail of stat");//perror打印有erron返回的函数的错误信息

return -1;

}

// printf("\n%d\n",st.st_mode);

if(S_ISREG(st.st_mode))//判断文件的权限

printf("-");

if(S_ISDIR(st.st_mode))

printf("d");

if((st.st_mode & S_IRUSR)== S_IRUSR)

printf("r");

else printf("-");

if((st.st_mode & S_IWUSR)== S_IWUSR)

printf("w");

else printf("-");

if((st.st_mode & S_IXUSR)== S_IXUSR)

printf("x");

else printf("-");

if((st.st_mode & S_IRGRP)== S_IRGRP)

printf("r");

else printf("-");

if((st.st_mode & S_IWGRP)== S_IWGRP)

printf("w");

else printf("-");

if((st.st_mode & S_IXGRP)== S_IXGRP)

printf("x");

else printf("-");

if((st.st_mode & S_IROTH)== S_IROTH)

printf("r");

else printf("-");

if((st.st_mode & S_IWOTH)== S_IWOTH)

printf("w");

else printf("-");

if((st.st_mode & S_IXOTH)== S_IXOTH)

printf("x");

else printf("-");

time=ctime(&st.st_ctime);

i=strlen(time);

*(time+i-1)=*(time+i);

//getpwuid得到文件的用户ID  getgrgid得到文件的组ID

printf(" %5ld ",st.st_nlink);

printf("%5s %5s %7ld %5s %s\n",getpwuid(st.st_uid)->pw_name,getgrgid(st.st_gid)->gr_name,st.st_size,time,name);

return 0;

}

 

int main(int argc, const char *argv[])

{

DIR *dr=NULL;

int len,size;

struct dirent *buf;

char* p=NULL;

char* path=NULL;

if(argc<2)//文件延展性

{

return -1;

}

if((dr=opendir(argv[1]))==NULL)//打开目录,返回一个指向DIR的指针

{

perror("fail of opendir");

return -2;

}

while(buf=readdir(dr))//扫描目录,返回一个结构体指针,结构体中保存目录中的有关资料

{

path=malloc(strlen(argv[1])+strlen(buf->d_name)+2);//因为不知道文件长度,每次读取重新开辟空间

strcpy(path,argv[1]);//将目录copypath所指向空间的头,实现目录在前,文件在后的规范

strcat(path,buf->d_name);//将文件名添加在目录的后面

ss(path,buf->d_name);//调用函数,用stat得到文件的详细信息并打印

free(path);//释放这个指针,高诉系统,这片空间用完了,你可以使用了

path=NULL;//需要注意,释放不代表清零,数据依旧存在,指针依旧指向这片空间,为避免危险操作,将指针指向NULL

}

closedir(dr);//关闭目录

return 0;

}

[拓展]

1.getpwuid 

struct passwd *getpwuid(uid_t uid);

//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 */

};

 

2.getgrgid

struct group *getgrgid(gid_t gid);

//group结构体

struct group

{

    char   *gr_name;       /* group name */

    char   *gr_passwd;     /* group password */

    gid_t   gr_gid;        /* group ID */

    char  **gr_mem;        /* group members */

};

 

3. readlink

ssize_t readlink(const char *path, char *buf, size_t bufsiz);

 

4. localtime

struct tm *localtime(const time_t *timep);

//tm结构体

struct tm

{

    int tm_sec;         /* seconds */

    int tm_min;         /* minutes */

    int tm_hour;        /* hours */

    int tm_mday;        /* day of the month */

    int tm_mon;         /* month */

    int tm_year;        /* year */

    int tm_wday;        /* day of the week */

    int tm_yday;        /* day in the year */

    int tm_isdst;       /* daylight saving time */

};

 

sudo !!  上一个命令权限不够,然后这个命令可以升级超级用户复制执行上一个命令


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值