1.Linux应用编程——文件
2016-06-12 20:40
459 查看
文件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,表示已到达文件尾或无可读取的数据,错误返回-1,count为0也返回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 */
};
实例:利用stat、opendir、readdir实现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]);//将目录copy到path所指向空间的头,实现目录在前,文件在后的规范
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 !! 上一个命令权限不够,然后这个命令可以升级超级用户复制执行上一个命令
文件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,表示已到达文件尾或无可读取的数据,错误返回-1,count为0也返回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 */
};
实例:利用stat、opendir、readdir实现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]);//将目录copy到path所指向空间的头,实现目录在前,文件在后的规范
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 !! 上一个命令权限不够,然后这个命令可以升级超级用户复制执行上一个命令
相关文章推荐
- Linux下基于socket多线程并发通信的实现
- LINUX修改、增加IP的方法,一张网卡绑定多个IP
- LinuxC/C++编程(10)—socket本地通信
- Centos7安装配置NFS服务和挂载
- Linux下基于socket多线程并发通信的实现
- centos6.5 搭建fastdfs分布式存储图片
- linux下邮件查看命令
- linux给用户添加sudo权限
- Linux中的c语言实现类似迅雷那样的下载
- Linux下Rsync服务部署
- U盘安装CentOS7的最终解决方案
- CentOS下将php和mysql命令加入到环境变量中的几种方法
- CentOS下将php和mysql命令加入到环境变量中的几种方法
- CentOS下将php和mysql命令加入到环境变量中的几种方法
- Mac与Phy组成原理的简单分析
- Linux-centos7防火墙
- Linux 初学者 第一个快捷键
- centos 下 安装 vnc 、vnc+xrdp,teamview 使用记录
- 将linux系统安装到U盘
- linux 字符设备