一、文件操作介绍介绍
编程主要是应用为王,例如:账单、游戏进度、配置文件等。
学习Linux文件,主要关心的是如何使用代码来操作文件,例如用代码来实现文件的创建,打开,编辑等自动化执行。
在windows手动修改文件主要有一下步骤:
1.打开/创建文档
2.编辑文档
3.保存文档
4.关闭文档
那么Linux呢?需要用Linux的vi工具来编写,通过编程来实现这一操作。
但Linux系统为我们提供了一系列的API:
打开:open
读写:read/write
光标定位:lseek
关闭:close
二、文件操作函数及代码示例
1.打开/创建文件
有三个函数操作:
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:表示要打开的文件名(含路径,缺省为当前路径)
flags:
O_RDONLY : 只读打开 O_WRONLY 只写打开 O_RDWR 可读可写打开
附带权限后,打开文件只能按这种权限来操作,另外以下参数是可选择的。
O_CREAT: 文件不存在则创建,使用时需说明第三个参数mode来说明该新文件的存取许可权限
O_EXCL: 同时指定了OCREAT,而文件存在,则出错。
O_APPEND : 每次写时都加到文件的尾端
O_TRUNC :属性去打开文件时,如果文件有内容,而且只读或只写成功打开,将其长度截短为0。
Mode :一定是在flags中使用了O_CREAT标志,表示文件的访问权限。
代码展示:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> //open所包含的三个头文件
#include <stdio.h>
int main()
{
int fd;
fd = open("./file1",O_RDWR); //fd为文件描述符,非负整数,文件不存在时为-1
if(fd == -1){
printf("open file failed\n");
fd = open("file1",O_RDWR|O_CREAT,0600); //0600为文件权限
if(fd > 0){
printf("create file1 success\n");
}
}
}
2.写入文件
ssize_t write(int fd, const void *buf, size_t count);
参数说明:
fd为打开的文件描述符
const void *buf :缓冲区指针指向内存里面的数据写入到打开的文件中
size_t count : 写入的字节数
代码展示:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h> //write的头文件
#include <string.h>
int main()
{
int fd;
char *buf = "I'm handsome!";
fd = open("./file1",O_RDWR);
if(fd == -1){
printf("open file failed\n");
fd = open("file1",O_RDWR|O_CREAT,0600);
if(fd > 0){
printf("create file1 success\n");
}
}
printf("open success : fd = %d\n",fd);
// ssize_t write(int fd, const void *buf, size_t count);
int n_write = write(fd,buf,strlen(buf)); //成功,文件描述符为写入的字节数,失败为-1
}
3.读取文件
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> //read头文件
#include <string.h>
int main()
{
int fd;
char *buf = "I'm handsome!";
fd = open("./file1",O_RDWR);
if(fd == -1){
printf("open file failed\n");
fd = open("file1",O_RDWR|O_CREAT,0600);
if(fd > 0){
printf("create file1 success\n");
}
}
printf("open success : fd = %d\n",fd);
// ssize_t write(int fd, const void *buf, size_t count);
int n_write = write(fd,buf,strlen(buf)); //成功,文件描述符为写入的字节数,失败为-1
close(fd);
fd = open("./file1",O_RDWR); //文件光标问题需要此操作,重新定位
char *readBuf;
readBuf = (char *)malloc(sizeof(char)*n_write + 1);
// ssize_t read(int fd, void *buf, size_t count);
int n_read = read(fd,readBuf,n_write);
printf("read: %d,context:%s\n",n_read,readBuf);
close(fd);
return 0;
}
4.文件的光标移动
off_t lseek(int fd, off_t offset, int whence);
参数说明:
fd:打开的文件描述符
off_t offset:偏移值
whence:固定点的一个位置,有三个位置分别为SEEK_SET(头)、SEEK_END(尾)、SEEK_CURT(当前位置)
代码展示:
#include <sys/types.h> //lseek头文件
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
int fd;
char *buf = "I'm handsome!";
fd = open("./file1",O_RDWR);
if(fd == -1){
printf("open file failed\n");
fd = open("file1",O_RDWR|O_CREAT,0600);
if(fd > 0){
printf("create file1 success\n");
}
}
printf("open success : fd = %d\n",fd);
// ssize_t write(int fd, const void *buf, size_t count);
int n_write = write(fd,buf,strlen(buf)); //成功,文件描述符为写入的字节数,失败为-1
char *readBuf;
readBuf = (char *)malloc(sizeof(char)*n_write + 1);
// off_t lseek(int fd, off_t offset, int whence);
lseek(fd,-13,SEEK_CUR); //光标定位
// lseek(fd,0,SEEK_SET);
// lseek(fd,-13,SEEK_END);
// ssize_t read(int fd, void *buf, size_t count);
int n_read = read(fd,readBuf,n_write);
printf("read: %d,context:%s\n",n_read,readBuf);
close(fd);
return 0;
}
对于以上的文件描述符做个简单的介绍:
1.对于内核而言,所有打开文件都由文件描述符引用。文件描述符是一个非负整数。当打开一个现存文件或者创建一个新文件时,内核向进程返回一个描述符。当读写一个文件时,用open和crea返回的文件描述符标识改文件,将其作为参数传递给read和write。
2.文件描述符,这个数字在一个进程中表示一个特定含义,当我们open一个文件时,操作系统在内存中构建了一些数据结构来表示这个动态文件,然后返回给应用程序一个数字作为文件描述符,这个数字就和我们内存中维护的这个动态文件的这些数据结构绑定上了,以后我们应用程序如果要操作这个动态文件,只需要用这个文件描述符区分。
3.文件描述符的作用域就是当前进程,出了这个进程文件描述符就没有意义了。