前言
1.在Linux中要操作一个文件,一航先是打开一个文件,得到文件描述符,然后对文件进行读写操作(或者其他操作),最后关闭文件即可。
2.强调一点:我们对文件进行操作时候,一定要先打开文件,打开成功后才能操作,如果打开失败,就不用进行后面的操作了,最后读写完成后,一定要关闭文件,否则会造成文件损坏。
3.文件平时是存放在块设备中的文件系统文件中的,我们把这种文件叫做静态文件,当我们去open打开一个文件时,Linux内核做的操作包括:在内核在进程中建立一个打开文件的数据结构,记录下我们打开的这个文件;内核在内存中申请一段内存,并且将静态文件的内容从块设备中读取到内核中特定地址管理存放(叫动态文件)。
4.打开文件以后,以后对这个文件的读写操作,都是针对内存中的这一份动态文件的,而不是针对静态文件的。当然我们针对动态文件进行读写以后,此时内存中动态文件和块设备文件中的静态文件就不同步了,当我们close关闭动态文件时,close内部内核将内存中的动态文件的内容去更新(同步)块设备中的静态文件。
5.这么设计的原因:块设备本身读写非常不灵活,是按块来读写的,而内存是按字节单位操作的,而且可以随机操作,很灵活。
一、打开/创建文件
#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);
Pathname: 要打开的文件名(含路径,缺少为当前路径)
Flages: O_RDONLY只读打开 ,O_WRONLY只写打开 , O_RDWR可读可写打开
当我们附带权限后,打开的文件就只能按照这种权限来操作。
以上三个参数中应当只指定一个,下列常数是可选择的:
O_CREAT
若文件不存在则创建它。使用此选项时,需要同时说明第三个参数mode。用其说明该文件的存取许可权限。
O_EXCL
如果同时指定O_CREAT,而文件已经存在,打开文件失败,返回值是-1。
O_APPEND
每次写时都加到文件的尾端。
O_TRUNC
去打开文件时,如果这个文件中本来是有内容的,而且为只写或可读可写成功打开,则将其长度截短为0。
Mode:一定是在flags中使用了O_CREAT标志,mode记录待创建的文件的访问权限。
创建文件creat函数
Pathname:要创建的文件名(包含路径、缺少为当前路径)
Mode:创建模式
常见的创建模式:
宏表示 | 数字 | 情况 |
---|---|---|
S_IRUSR | 4 | 可读 |
S_IWUSR | 2 | 可写 |
S_IXUSR | 1 | 可执行 |
S_IRWXU | 7 | 可读、可写、可执行 |
例子:
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>
int main()
{
int fd;
fd=open("./file1",O_RDWR);//如果file1存在不执行if语句
if(fd==-1){
printf("open file1 falled\n");
fd=open("./file1",O_RDWR|O_CREAT,0600);//可读可写的方式创建file1
if(fd>0){
printf("create file1 success!\n");
// printf("fd=%d\n",fd);
}
}
close(fd);
return 0;
}
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>
int main()
{
int fd;
fd=open("./file1",O_RDWR|O_CREAT|O_EXCL,0600);
if(fd==-1){
printf("file1 Chunzai\n");
}
return 0;
}
二、写入文件
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
例子
#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="Study Linux";
fd=open("./file1",O_RDWR);
if(fd==-1){
printf("open file1 fallde\n");
fd=open("./file1",O_RDWR|O_CREAT,0600);
if(fd>0){
printf("create file1 success!\n");
// printf("fd=%d\n",fd);
}
}
printf("open success: fd=%d\n",fd);
write(fd,buf,strlen(buf));//将buf中的数据写入到打开的文件fd中,长度为strlen(buf)
close(fd);
return 0;
}
三、读取文件
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
例子
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
int main()
{
int fd;
char *buf="Study Linux";
fd=open("./file1",O_RDWR);
if(fd==-1){
printf("open file1 fallde\n");
fd=open("./file1",O_RDWR|O_CREAT,0600);
if(fd>0){
printf("create file1 success!\n");
// printf("fd=%d\n",fd);
}
}
printf("open success: fd=%d\n",fd);
int n_write= write(fd,buf,strlen(buf));
if(n_write!=-1){
printf("wriet %d byte to file1\n",n_write);
}
char *readBuf;
readBuf=(char *) malloc(sizeof(char)*n_write+1);
int n_read=read(fd,readBuf,n_write);//从fd文件中读取数据存放到readBuf中,长度为n_write,但是在此程序中,读出为空,光标问题。
printf("read %d , context: %s\n",n_read,readBuf);
close(fd);
return 0;
}
四、文件“光标”位置
解决读取文件为空,方法一:关闭文件从新打开
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
int main()
{
int fd;
char *buf="Study Linux";
fd=open("./file1",O_RDWR);
if(fd==-1){
printf("open file1 fallde\n");
fd=open("./file1",O_RDWR|O_CREAT,0600);
if(fd>0){
printf("create file1 success!\n");
// printf("fd=%d\n",fd);
}
}
printf("open success: fd=%d\n",fd);
int n_write= write(fd,buf,strlen(buf));
if(n_write!=-1){
printf("wriet %d byte to file1\n",n_write);
}
close(fd);
fd=open("./file1",O_RDWR);
char *readBuf;
readBuf=(char *) malloc(sizeof(char)*n_write+1);
int n_read=read(fd,readBuf,n_write);
printf("read %d , context: %s\n",n_read,readBuf);
close(fd);
return 0;
}
方法二:重新定义光标
运用 lseek()
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
int main()
{
int fd;
char *buf="Study Linux";
fd=open("./file1",O_RDWR);
if(fd==-1){
printf("open file1 fallde\n");
fd=open("./file1",O_RDWR|O_CREAT,0600);
if(fd>0){
printf("create file1 success!\n");
// printf("fd=%d\n",fd);
}
}
printf("open success: fd=%d\n",fd);
int n_write= write(fd,buf,strlen(buf));
if(n_write!=-1){
printf("wriet %d byte to file1\n",n_write);
}
lseek(fd,0,SEEK_SET);//光标相对于头偏移量是0,即光标在头
char *readBuf;
readBuf=(char *) malloc(sizeof(char)*n_write+1);
int n_read=read(fd,readBuf,n_write);
printf("read %d , context: %s\n",n_read,readBuf);
close(fd);
return 0;
}
lseek()的另一运用:计算文件的大小
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
int fd;
// char *buf="chenlichen hen shuai";
fd=open("./file1",O_RDWR);
int file1size=lseek(fd,0,SEEK_END);//光标相对于尾巴的偏移值是0,即光标在尾巴
printf("file1's size is:%d\n",file1size);
close(fd);
return 0;
}