博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux 基于文件描述符的文件操作 open,close,read,write,lseek,stat,fstat,ftruncate
阅读量:2432 次
发布时间:2019-05-10

本文共 6990 字,大约阅读时间需要 23 分钟。

基于文件描述符的文件操作

打开、创建和关闭文件

#include 
//头文件 #include
#include
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 
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 
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 
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 
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 
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 
#include
//包含 exit #include
#include
#include
#include
//用 perror 输出错误 #include
#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 
int ftruncate(int fd, off_t length);

函数 ftruncate 会将参数 fd 指定的文件大小改为参数 length 指定的大小。参数 fd 为已打开的文

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

#include 
#include
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 
#include
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 
#include
#include
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
#include
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 
#include
#include
#include
#include
#include
#include
#include
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; }

转载地址:http://faxmb.baihongyu.com/

你可能感兴趣的文章
MYSQL列类型参考(转)
查看>>
Windows CE .NET 应用程序开发:我有哪些选择?(转)
查看>>
查看ORACLE数据库信息的一些SQL(转)
查看>>
通向Windows CE(转)
查看>>
病毒及木马预警一周播报(06.04.17~04.23)(转)
查看>>
系统安全漏洞扫描绝佳助手之Nmap详解(转)
查看>>
终于以一种奇怪的方式搞定了Oracle的临时表问题(转)
查看>>
数据实时同步或抽取上收的技术分析(转)
查看>>
Pocket PC 实时处理(转)
查看>>
解决WAP中的安全问题(转)
查看>>
超低配置机器无盘网吧的安装方法(转)
查看>>
为 Microsoft Smartphone 开发应用程序(转)
查看>>
一种可以穿透还原卡和还原软件的代码(转)
查看>>
在网吧中如何使用双ADSL线路(转)
查看>>
第五章 WMLScript脚本程序设计(上)(转)
查看>>
何得知Recordset里的记录数(转)
查看>>
蜘蛛:百度收录减少的原因和解决办法(转)
查看>>
ITPUB
查看>>
网站在搜索引擎中排名的影响因素--meta(转)
查看>>
如何在 Oracle JDeveloper 中进行 Ajax 编程(转)
查看>>