【Linux】在Linux下文件io使用(二)
在linux下,一切皆文件。当文件被打开时,会返回文件描述符用于操作该文件,从shell中运行一个进程,默认会有3个文件描述符存在(0、1、2); 0表示标准输入,1表示标准输出,2表示标准错误。一个进程当前有哪些打开的文件描述符可以通过/proc/进程ID/fd目录查看
在文件夹下的系统调用
int mkdir(const char *pathname,mode_t mode) | 创建文件夹 |
---|---|
int rmdir(const char *pathname); | 删除文件夹 |
DIR *opendir(const char *pathname); | 打开文件夹 |
struct dirent *readdir(DIR *dp); | 读文件夹 |
int closeddir (DIR *dp); | 关闭文件夹 |
int chdir(const char *pathname); | 改变工作目录 |
其中readdir()系统调用的struct dirent定义如下:
struct dirent
{
long d_ino; /* inode number 索引节点号 */
off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
unsigned short d_reclen; /* length of this d_name 文件名长 */
unsigned char d_type; /* the type of d_name 文件类型 */
char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
}
系统调用
creat
int creat (const char *pathname,mode_t mode);
他等价于:
open(pathname,O_CREAT | O_TRUNC | O_WRONLY,mode);
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
int main()
{
if( creat("/aicamel/boa/file.txt",0777) < 0 )
{
printf("文件创建失败!\n");
} else
{
printf("文件创建成功!\n");
}
return 0;
}
dup()和dup2()
#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);
功能:
复制文件描述符,使多个文件描述符指向同一个文件。
返回值:
成功:dup函数返回当前系统可用的最小整数值。
dup2函数返回第一个不小于newfd的整数值。也就是分为两种情况:
如果newfd已经打开,则先将其关闭,再复制文件描述符。
如果newfd等于oldfd,则dup2返回newfd, 而不关闭它。
失败:均返回-1,并设置errno
int main(int argc, char *argv)
{
int fd = -1;
fd = open("test.txt",O_RDWR|O_CREAT|O_TRUNC,0666);
if(fd < 0)
{
printf("Open file failure: %s\n",strerror(errno));
return 0;
}
dup2(fd,STDIN_FILENO);//标准输入重定向到test.txt文件去
dup2(fd , STDOUT_FILENO);//标准输出重定向到test.txt文件去
dup2(fd,STDERR_FILENO);//标准出错重定向到test.txt文件去
printf("fd=%d\n",fd);
close(fd);
return 0;
}
标准输入 | 标准输入 | 标准出错 |
---|---|---|
STDIN_FILENO | STDOUT_FILENO | STDERR_FILENO |
stdin | stdout | stderr |
可以看到fd=3,说明文件标准重定向成功
stat和fstat
这两个函数都是用来返回文件或目录的相关信息,只是stat()的第一个参数是文件名,而fstat()的第一个参数是文件打开的相应文件描述符
int stat(const char * restrict path, struct stat *restrict buf);
int fstat(int fd, struct stat *buf);
功能:
两个函数都是用来返回文件或目录的相关信息
restrict path: 参数是文件名
fd :参数是文件打开的相应文件描述符
struct stat结构体如下
struct stat {
dev_t st_dev; /* 文件的设备编号 */
ino_t st_ino; /* 索引结点编号 */
mode_t st_mode; /* 文件类型和权限*/
nlink_t st_nlink; /*硬链接数 */
uid_t st_uid; /*用户ID*/
gid_t st_gid; /* 组ID*/
dev_t st_rdev; /* 设备类型(若此文件为设备文件,则为设备编号*/
off_t st_size; /* 文件大小*/
blksize_t st_blksize; /*文件系统的I/O缓冲区大小*/
blkcnt_t st_blocks; /* 块数 */
time_t st_atime; /* 访问时间 */
time_t st_mtime; /* 修改时间 */
time_t st_ctime; /* 更改时间 */
};
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
int main (int argc, char **argv)
{
struct stat stbuf;
stat("stat.c", &stbuf);
printf("File Mode: %o Real Size: %luB, Space Size: %luB\n", stbuf.st_mode,
stbuf.st_size,stbuf.st_blksize);
return 0;
}
access():判断文件的权限位
int access(const char *path,int mode);
参数path 是访问文件所在的路径名,mode是访问判断模式,
具体含义如下:
R_OK 只判断是否有读权限
W_OK 只判断是否有写权限
X_OK 判断是否有执行权限
F_OK 只判断是否存在
功能:
确定文件或文件夹的访问权限。如果指定的存取方式有效,则函数返回0,否则函数返回-1。
#include <stdio.h>
#include <unistd.h>
#define TEST_FILE "access.c"
int main(void)
{
if( access(TEST_FILE, F_OK)!=0 )
{
printf("File %s not exist!\n", TEST_FILE);
return 0;
}
printf("File %s exist!\n", TEST_FILE);
if(access(TEST_FILE, R_OK)==0)
printf("READ OK\n");
if(access(TEST_FILE, W_OK)==0)
printf("WRITE OK\n");
if(access(TEST_FILE, X_OK)==0)
printf("EXEC OK\n");
return 0;
}
mkdir()创建一个文件夹
函数原型如下:
int mkdir(const char *pathname, mode_t mode);
函数说明:
mkdir()函数以mode方式创建一个以参数pathname命名的目录,mode定义新创建目录的权限。
返回值:
若目录创建成功,则返回0;否则返回-1,并将错误记录到全局变量errno中。
if(mkdir(TXT_DIR,0755)<0)
{
printf("创建新的'%s'文件夹失败:%s\n",TXT_DIR,strerror(errno));
return -1;
}
chdir()改变工作目录
chdir 是C语言中的一个系统调用函数(同cd),用于改变当前工作目录
其参数为Path 目标目录,可以是绝对目录或相对目录。
int chdir(const char *path);
-参数*path;文件路径
-返回值;成功返回0,错误返回-1
if(chdir(TXT_DIR)<0)
{
printf("更改目录'%s'文件失败:%s\n",TXT_DIR,strerror(errno));
rv = -2;
goto cleanup;
}
opendir()打开一个文件夹
函数原型
DIR* opendir (const char * path );
获取path子目录下的所由文件和目录的列表,如果path是个文件则返回值为NULL
功能
打开一个目录,在失败的时候返回一个空的指针。
DIR 结构体的原型为:struct_dirstream
在linux系统中:
typedef struct __dirstream DIR;
struct __dirstream
{
void *__fd; /* `struct hurd_fd' pointer for descriptor. */
char *__data; /* Directory block. */
int __entry_data; /* Entry number `__data' corresponds to. */
char *__ptr; /* Current pointer into the block. */
int __entry_ptr; /* Entry number `__ptr' corresponds to. */
size_t __allocation; /* Space allocated for the block. */
size_t __size; /* Total valid data in the block. */
__libc_lock_define (, __lock) /* Mutex lock for this structure. */
};
if((dirp = opendir(TXT_DIR))==NULL)
{
printf("打开'%s'文件夹失败:%s\n",TXT_DIR,strerror(errno));
rv = -6;
goto cleanup;
}
while((direntp = readdir(dirp)) !=NULL)
{
printf("文件夹所以的文件:%s\n",direntp->d_name);//在struct dirent结构体有
}
readdir()在文件夹下所以文件的信息
函数原型
struct dirent* readdir(DIR* dir_handle); (个人理解循环读取dir,文件夹和文件都读)
功能
读取opendir 返回值的那个列表
返回值
返回dirent结构体指针,dirent结构体成员如下,(文件和目录都行)
dirent的结构体
struct dirent
{
ino_t d_ino; //此目录进入点的inode
ff_t d_off; //目录文件开头至此目录进入点的位移
signed short int d_reclen; //d_name 的长度,不包含NULL
unsigned char d_type; //d_name 所指的文件类型
har d_name[256]; //文件名
}
代码实现
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#define TXT_DIR "dir"
int main(int argc, char **argv)
{
int fd1;
int rv ;
int fd2;
DIR *dirp;
struct dirent *direntp;
if(mkdir(TXT_DIR,0755)<0)
{
printf("创建新的'%s'文件夹失败:%s\n",TXT_DIR,strerror(errno));
return -1;
}
if(chdir(TXT_DIR)<0)
{
printf("更改目录'%s'文件失败:%s\n",TXT_DIR,strerror(errno));
rv = -2;
goto cleanup;
}
if((fd1 = creat("test1.txt",0644))<0)
{
printf("文件创建失败:%s\n",strerror(errno));
rv = -3;
goto cleanup;
}
if((fd2 = creat("test2.txt",0644))<0)
{
printf("文件创建文件失败:%s\n",strerror(errno));
rv = -4;
goto cleanup;
}
if(chdir("../")<0)
{
printf("更改目录到父'%s'文件夹下:%s\n",TXT_DIR,strerror(errno));
rv = -5;
goto cleanup;
}
if((dirp = opendir(TXT_DIR))==NULL)
{
printf("打开'%s'文件夹失败:%s\n",TXT_DIR,strerror(errno));
rv = -6;
goto cleanup;
}
while((direntp = readdir(dirp)) !=NULL)
{
printf("文件夹所以的文件:%s\n",direntp->d_name);//在struct dirent结构体有
}
//关闭所有的文件夹
closedir(dirp);
//关闭所有的文件
cleanup:
if(fd1 >=0)
{
close(fd1);
}
if(fd2 >=0)
{
close(fd2);
}
}
代码运行成功后,显示(test1.txt test2.txt … .)这四种文件