Linux系统编程-文件操作
前言:
Linux 中所有内容都是以文件的形式保存和管理的,即一切皆文件,普通文件是文件,硬件设备(键盘、监视器、硬盘、打印机)是文件,就连套接字(socket)、网络通信等资源也都是文件,这些文件能够使用访问接口(open、read、write)进行访问。本期来分享一下普通文件IO与高级文件IO的使用!
文件的操作
1.1open-文件的打开
参数说明:
#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_mode);
说明:
pathname 是打开的文件名
flag:
O_RDONLY
只读打开,
O_WRONLY
只写打开 ,
O_RDWR
可读可写打开。
mode:一定是在flags中使用了O_CREAT标志,mode记录待创建的文件的访问权限。
另:
O_CREAT 若文件不存在则创建它。注:使用时,需要同时说明第三个参数mode
O_EXCL 如果同时指定了OCREAT,而文件已经存在,则错误 ,返回-1 //判断一个文件是否存在
O_APPEND 每次写时都加到文件的尾端 // 在原有的文件下加在尾端
O_TRUNC 属性去打开文件时,如果这个文件本来是有内容的,而且为只读或只写成功打开,则将其长度截短为0;//把原有的内容删除,再加上写入内容
fd文件描述符,当fd>0时,open成功,当fd=-1时,打开失败;
下列为文件打开的代码范例:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
int fd;
fd = open("file1",O_RDWR);
if(fd == -1){
printf("open fail\n");
open("file1",O_RDWR|O_CREAT,0600);|是或操作,0600可读可写
printf("create success!\n");
}
return 0;
}
-代表他是一个普通文件,rwx代表当前用户的权限
r—- 4 可读 w—— 2 可写 x—可执行 1
0600—-6给用户所有者可读可写,0–同组,0–其他组
1.2 creat-文件的创建
参数说明:
int creat(const char *filename,mode_t mode);
mode:创建模式
常见的创建模式:
宏表示 数字
S_IRUSR 4 可读
S_IWUSR 2 可写
S_IXUSR 1 可执行
S_IRWXU 7 可读可写可执行
2.1write-文件的写入
参数说明:
#include <unistd.h>
ssize_t write(int fd,const void *buf,size_t count);
buf是个缓冲区,size_t cont 写入多少个字节
ssize_t write返回表示读了多少个字节
eg:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
int fd;
char *buf = "you are beautiful!";
fd = open("file1",O_RDWR);
if(fd == -1){
printf("open fail\n");
}
fd = open("file1",O_RDWR|O_CREAT,0600);
if(fd>0){
printf("create success!\n");
}
write(fd,buf,strlen(buf));
close(fd);
return 0;
}
3.1read-文件的读取
参数说明:
#include <unistd.h>
ssize_t read(int fd,void *buf,size_t count);
ssize_t read 返回表示读了多少个字节
eg:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
int fd;
char readBuf[128]={0};
fd = open("file1",O_RDWR);
if(fd == -1){
printf("open fail\n");
}
fd = open("file1",O_RDWR|O_CREAT,0600);
if(fd>0){
printf("create success!\n");
}
read(fd,readBuf,strlen(readBuf));
printf("read buf :%s\n",readBuf);
close(fd);
return 0;
}
4.1 lseek-光标的移动
参数说明:
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd,off_t offset,int whence);
off_t lseek: 返回偏移的长度
whence:
SEEK_SET: 指向头
SEEK_CUR: 指向当前位置
SEEK_END: 指向尾
offset是相对whence偏移的大小
5.1文件描述符
在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件、目录文件、链接文件和设备文件。在操作这些所谓的文件的时候,我们每操作一次就找一次名字,这会耗费大量的时间和效率。所以Linux中规定每一个文件对应一个索引,这样要操作文件的时候,我们直接找到索引就可以对其进行操作了。
文件描述符(file descriptor)就是内核为了高效管理这些已经被打开的文件所创建的索引,他是一个非负整数,用于指代被打开的文件,所有执行I/O操作的系统调用都通过文件描述符来实现。
用文件io实现一个cp指令
eg:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char **argv)
{
int fdDes;
int fdSrc;
char *readBuf = NULL;
if(argc != 3){
printf("program error");
exit(-1);
}
fdSrc = open(argv[1],O_RDWR);
int size = lseek(fdSrc,0,SEEK_END); //用lseek光标移动计算文件大小
lseek(fdSrc,0,SEEK_SET); //注:光标移走后要移回头,不然读到的数据是尾,数据为空
readBuf = (char *)malloc(sizeof(char)*size+8);
int read_n = read(fdSrc,readBuf,size);
fdDes = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0600);
write(fdDes,readBuf,strlen(readBuf));
close(fdDes);
close(fdSrc);
return 0;
}
高级文件IO
fopen()函数
FILE *fopen(char *filename, char *mode)
mode 打开模式:
r 只读方式打开一个文本文件
rb 只读方式打开一个二进制文件
w 只写方式打开一个文本文件
wb 只写方式打开一个二进制文件
a 追加方式打开一个文本文件
ab 追加方式打开一个二进制文件
r+ 可读可写方式打开一个文本文件
rb+ 可读可写方式打开一个二进制文件
w+ 可读可写方式创建一个文本文件
wb+ 可读可写方式生成一个二进制文件
a+ 可读可写追加方式打开一个文本文件
ab+ 可读可写方式追加一个二进制文件
fwrite()函数
1.作用:在C语言中fwrite()函数常用语将一块内存区域中的数据写入到本地文本。
size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);
-- buffer:指向数据块的指针
-- size:每个数据的大小,单位为Byte(例如:sizeof(int)就是4)
-- count:数据个数
-- stream:文件指针,从哪里读buf
fread()函数
1 作用:从一个文件流中读取数据
2 函数原型如下:
size_t fread(void *buffer, size_t size, size_t count, FILE *stream);
-- buffer:指向数据块的指针
-- size:每个数据的大小,单位为Byte(例如:sizeof(int)就是4)
-- count:数据个数
-- stream:文件指针
注意:返回值随着调用格式的不同而不同:
(1) 调用格式:fread(buf,sizeof(buf),1,fp);
读取成功时:当读取的数据量正好是sizeof(buf)个Byte时,返回值为1(即count)
否则返回值为0(读取数据量小于sizeof(buf))
(2)调用格式:fread(buf,1,sizeof(buf),fp);
读取成功返回值为实际读回的数据个数(单位为Byte)
fseek()函数:
跟lseek一样
注意:返回值随着调用格式的不同而不同:
(1) 调用格式:fread(buf,sizeof(buf),1,fp);
读取成功时:当读取的数据量正好是sizeof(buf)个Byte时,返回值为1(即count)
否则返回值为0(读取数据量小于sizeof(buf))
(2)调用格式:fread(buf,1,sizeof(buf),fp);
读取成功返回值为实际读回的数据个数(单位为Byte)
eg:
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fd;
char *buf = "hello!";
char readBuf[128]={0};
//FILE *fopen(char *filename, char *mode)
fd = fopen("./chen.txt","w+");
//size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);
fwrite(buf,sizeof(char)*strlen(buf),1,fd);
fseek(fd,0,SEEK_SET);
fread(readBuf,sizeof(char)*strlen(buf),1,fd);
return 0;
}
fgetc、fputc、feof
int fgetc(FILE *stream) *//从stream流中读取一个字符* i
nt fputc(int char, FILE *stream) *//把字符char 写到stream流中*
int feof(FILE *stream) *//测试文件结束标识符*
open与fopen的区别
open和fopen的区别:
前者属于低级IO,后者是高级IO。
前者返回一个文件描述符,后者返回一个文件指针。
前者无缓冲,后者有缓冲。
前者与 read, write 等配合使用, 后者与 fread, fwrite等配合使用。
后者是在前者的基础上扩充而来的,在大多数情况下,用后者