Linux 基于文件描述符的文件操作 open,close,read,write,lseek,stat,fstat,ftruncate

打开、创建和关闭文件

#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);//文件名  打开方式  权限 
int creat(const char *pathname, mode_t mode);  //文件名  权限   
creat 函数等价于open(pathname,O_CREAT|O_TRUNC|O_WRONLY,mode); 

open()函数出错时返回-1,相关参数如下:
flags 和 mode 都是一组掩码的合成值,flags 表示打开或创建的方式,mode 表示文件的访问权限。 mode参数只有在建立新文件时才会生效(flags中包含O_CREAT),表示新建文件的权限,但最终所建文件的权限会受到umask值所影响,因此该文件权限应该为(mode-umaks)。
flags 的可选项有

O_RDONLY     以只读的方式打开 
O_WRONLY     以只写的方式打开 
O_RDWR       以读写的方式打开 
O_CREAT      如果文件不存在,则创建文件 
O_EXCL       仅与 O_CREAT 连用,如果文件已存在,则强制 open 失败 
O_TRUNC      如果文件存在,将文件的长度截至 0 
O_APPEND     已追加的方式打开文件, 每次调用 write 时,文件指针自动先移到文件尾,用于多进程写一个文件的情况。 
O_NONBLOCK   非阻塞方式打开,无论有无数据读取或等待,都会立即返回进程之中。 
O_NODELAY    非阻塞方式打开 
O_SYNC       同步打开文件,只有在数据被真正写入物理设备设备后才返回 

mode的可选项有:

mode 的可选项有: 
S_IRWXU 00700 权限,代表该文件所有者具有可读、可写及可执行的权限。 
S_IRUSR 00400 权限,代表该文件所有者具有可读取的权限。 
S_IWUSR 00200 权限,代表该文件所有者具有可写入的权限。 
S_IXUSR 00100 权限,代表该文件所有者具有可执行的权限。 
 
S_IRWXG 00070 权限,代表该文件用户组具有可读、可写及可执行的权限。 
S_IRGRP 00040 权限,代表该文件用户组具有可读的权限。 
S_IWGRP 00020 权限,代表该文件用户组具有可写入的权限。 
S_IXGRP 00010 权限,代表该文件用户组具有可执行的权限。 
 
S_IRWXO 00007 权限,代表其他用户具有可读、可写及可执行的权限。 
S_IROTH 00004 权限,代表其他用户具有可读的权限 
S_IWOTH 00002 权限,代表其他用户具有可写入的权限。 
S_IXOTH 00001 权限,代表其他用户具有可执行的权限。

close 用于文件的关闭:

int close(int fd);    //fd 表示文件描述符,是先前由 open 或 creat 创建文件时的返回值。 

文件使用完毕后,应该调用 close 关闭它,一旦调用 close,则该进程对文件所加的锁全都被释放,并且使文件的打开引用计数减 1,只有文件的打开引用计数变为 0 以后,文件才会被真正的关闭。

#include <func.h>

int main(int argc, char* argv[])
{
    ARGS_CHECK(argc, 2);
    int fd;
    fd = open(argv[1],O_RDWR);
    ERROR_CHECK(fd, -1, "open");
    printf("fd=%d\n",fd);
    close(fd);
    return 0;
}
#include <func.h>

int main(int argc, char* argv[])
{
    ARGS_CHECK(argc, 2);
    int fd;
    fd = open(argv[1],O_RDWR|O_CREAT,0666);
    ERROR_CHECK(fd, -1, "open");
    printf("fd=%d\n",fd);
    return 0;
}

读写文件

#include <unistd.h> 
ssize_t read(int fd, void *buf, size_t count);    //文件描述符  缓冲区  长度 
ssize_t write(int fd, const void *buf, size_t count); 

fd:文件描述符 buf:写入的字符串,传入指向字符串的指针 count:写入的字节数
对于read函数同理,buf为读出的缓冲区,count为读出的字节数
read 和 write 函数,出错返回-1,读取完了之后,返回 0, 其他情况返回读写的个数

read.c

#include <func.h>

int main(int argc, char* argv[])
{
    ARGS_CHECK(argc, 2);
    int fd;
    fd = open(argv[1],O_RDWR);
    ERROR_CHECK(fd, -1, "open");
    printf("fd=%d\n",fd);
    char buf[128]={0};
    int ret = read(fd,buf,sizeof(buf));
    printf("buf=%s,ret=%d\n",buf,ret);
    close(fd);
    return 0;
}

write.c

#include <func.h>

int main(int argc, char* argv[])
{
    ARGS_CHECK(argc, 2);
    int fd;
    fd = open(argv[1],O_RDWR);
    ERROR_CHECK(fd, -1, "open");
    printf("fd=%d\n",fd);
    int ret = write(fd,&fd,sizeof(int));
    printf("write count = %d\n",ret);
    close(fd);
    return 0;
}

案例:将 aaa.txt 中的内容复制到 bbb.txt 中,其中 bbb.txt 起初不存在

#include <stdio.h> 
#include <stdlib.h>       //包含 exit 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <errno.h>              //用 perror 输出错误 
#include <unistd.h> 
#define FILENAME1 "./aaa.txt"     //用宏定义文件的路径
#define FILENAME2 "./bbb.txt"
int main() 
{ 
    char buf[512] = {0}; 
    int fo1 = open(FILENAME1, O_RDONLY);  //fo1,fo2 都是文件描述词 
	int fo2 = creat(FILENAME2, 0755);     //创建文件 
	//int fo2 = open(FILENAME2, O_WRONLY | O_CREAT); 
    if( (-1 == fo1) || (-1 == fo2) ) 
	{ 
     	perror("open failed!\n"); 
		//用于输出错误信息.类似于:fputs(”open failed\n”,stderr); 
      	exit(-1); 
    } 
    int fr = 0; 
	while( (fr = read(fo1, buf, sizeof(buf))) > 0 ) 
	//如果 read 读取成功,返回的是长度,否则,返回-1 
    { 
        int fw = write(fo2, buf, fr); 
     	if( -1 == fw ) 
        { 
            perror("write failed!"); 
      		exit(-1); 
        } 
    } 
    close(fo1); 
    close(fo2); 
} 

改变文件大小

#include <unistd.h> 
int ftruncate(int fd, off_t length); 

函数 ftruncate 会将参数 fd 指定的文件大小改为参数 length 指定的大小。参数 fd 为已打开的文
件描述词,而且必须是以写入模式打开的文件。如果原来的文件大小比参数 length 大,则超过的
部分会被删去。
返回值 执行成功则返回 0,失败返回-1。

#include <func.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
    ARGS_CHECK(argc, 2);
    int fd;
    fd = open(argv[1],O_RDWR);
    ERROR_CHECK(fd, -1, "open");
    printf("fd=%d\n",fd);
    int ret = ftruncate(fd,50);
    ERROR_CHECK(ret,-1,"ftruncate");
    close(fd);
    return 0;
}
int main() 
{ 
    int fd = open("a.txt", O_WRONLY); 
    ftruncate(fd, 1000); 
    close(fd); 
    return 0; 
} 

文件定位

#include <sys/types.h> 
#include <unistd.h> 
off_t lseek(int fd, off_t offset, int whence);

函数 lseek 将文件指针设定到相对于 whence,偏移值为 offset 的位置
whence 可以是下面三个常量的一个

SEEK_SET 从文件头开始计算 
SEEK_CUR 从当前指针开始计算 
SEEK_END 从文件尾开始计算 

利用该函数可以实现文件空洞(对一个新建的空文件,可以定位到偏移文件开头 1024 个字节的地
方,在写入一个字符,则相当于给该文件分配了 1025 个字节的空间,形成文件空洞)通常用于多
进程间通信的时候的共享内存。

int main() 
{ 
    int fd = open("c.txt", O_WRONLY | O_CREAT); 
    lseek(fd, 1024, SEEK_SET); 
    write(fd, "a", 1); 
    close(fd); 
    return 0; 
} 

获取文件信息

可以通过 fstat 和 stat 函数获取文件信息,调用完毕后,文件信息被填充到结构体 struct stat变量中,函数原型为:

#include <sys/types.h> 
#include <sys/stat.h> 
#include <unistd.h> 
int stat(const char *file_name, struct stat *buf);    //文件名  stat 结构体指针 
int fstat(int fd, struct stat *buf);      //文件描述符   stat 结构体指针

结构体 stat 的定义为:

struct stat { 
           dev_t         st_dev;      /*如果是设备,返回设备表述符,否则为 0*/ 
           ino_t         st_ino;      /* i 节点号 */ 
           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;  /* 块大小*/ 
           blkcnt_t      st_blocks;   /* 块数 */ 
           time_t        st_atime;    /* 最后访问时间*/ 
           time_t        st_mtime;    /* 最后修改时间*/ 
           time_t        st_ctime;    /* 最后权限修改时间 */ 
    };

对于结构体的成员 st_mode,有一组宏可以进行文件类型的判断:

S_ISLNK(mode)  判断是否是符号链接 
S_ISREG(mode)  判断是否是普通文件 
S_ISDIR(mode)  判断是否是目录 
S_ISCHR(mode)  判断是否是字符型设备 
S_ISBLK(mode)  判断是否是块设备 
S_ISFIFO(mode) 判断是否是命名管道 
S_ISSOCK(mode) 判断是否是套接字 
#include<sys/stat.h> 
#include<unistd.h> 
int main() 
{ 
	struct stat buf; 
	stat (/etc/passwd”,&buf); 
	printf(/etc/passwd file size = %d \n”,buf.st_size);//st_size 可以得到文件大小 
	return 0;
} 
//如果用 fstat 函数实现,如下:  
int fd = open (/etc/passwd”,O_RDONLY);  //先获得文件描述符
fstat(fd, &buf);  
#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <sys/stat.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <time.h> 
 
int main() 
{ 
    int fd = open("/home/wangxiao/0926/a.txt", O_RDONLY); 
    if(fd == -1) 
    { 
        perror("open error"); 
        exit(-1);
        } 
  
    struct stat buf; 
    int iRet = fstat(fd, &buf); 
    if(iRet == -1) 
    { 
        perror("fstat error"); 
        exit(-1); 
    } 
  
    if(S_ISREG(buf.st_mode)) 
    { 
        printf("regular file!\n"); 
    } 
    if(S_ISDIR(buf.st_mode)) 
    { 
        printf("directory!\n"); 
    } 
    if(S_ISLNK(buf.st_mode)) 
    { 
        printf("link file!\n"); 
	} 
	printf("the size of file is : %d\n", buf.st_size); 
 
	time_t tt = buf.st_atime; 
	struct tm *pT = gmtime(&tt); 
	printf("%4d-%02d-%02d   %02d:%02d:%02d\n", (1900+pT->tm_year), (1+pT->tm_mon), 
pT->tm_mday, (8+pT->tm_hour), pT->tm_min, pT->tm_sec); 
	printf("the last access time is : %d\n", buf.st_atime); 
	close(fd); 
	return 0; 
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值