一、文件编程的概述
1.1 文件编程的API
打开 open
读写 write/read
光标定位 lseek
关闭 close
1.2 文件描述符
(1)对于内核而言,所有打开文件都由文件描述符引用,文件描述符是一个非负整数,当打开一个现存文件或者创建一个新文件时,内核向进程返回一个文件描述符。当读写一个文件时,用open 和 creat 返回的文件描述符标识该文件,将其作为参数传递给 read 和 write。
按照惯例,UNIX shell 使用文件描述符0与进程的标准输入相结合,文件描述符1与标准输出相结合,文件描述符2与标准错误输出相结合。
(2)、文件描还符,这个数字在一个进程中表示一个特定含义,当我08n一个文件时,操作系统在内存中构建了一些数据结构来表示这个动态文件,然后返回给应用程序一个数字作为文件描述符,这个数字就和我们内存中维护的这个动态文件的这些数据结构绑定上了,以后我们应用程序如果要操作这个动态文件,只需要用这个文件描述符区分。
(3)文件描述符的作用域就是当前进程,出了这个进程文件描述符就没有意义了。
(4)open函数打开文件,打开成功返回一个文件描述符,打开失败,返回-1。
1.3 文件编程的一般步骤
打开/创建文件 >> 读取文件/写入文件 >> 关闭文件
(1)在Linux中要操作一个文件,一般是先open打开一个文件,得到文件描述符,然后对文件进行读写操作(或其他操作),最后是olose关闭文件即可。
(2)强调一点:我们对文件进行操作时,一定要先打开文件,打开成功之后才能操作,如果打开失败,就不用进行后边的操作了,最后读写完成后,一定要关闭文件,否则会造成文件损坏。
(3)文件平时是存放在块设备中的文件系统文件中的,我们把这种文件叫静态文件,当我们去opn打开一个文件时,liux内核做的提作包括:内核在进程中建立一个打开文件的数据结构,记录下我们打开的这个文件:内核在内存中申请一段内存,并且将静态文件的内容从块设备中读取到内核中特定地址管理存放(叫动态文件)。
(4)打开文件以后,以后对这个文件的读写损作,都是针对内存中的这一份动态文件的,而并不是针对酶态文件的。当然我们对动态文件进行读写以后,此时内存中动态文件和块设备文件中的静态文件就不同步了,当我们cose天闭动态文件时,cose内部内核将内存中的动态文件的内容去更新(同步)块设备中的静态文件。
(5)为什么这么设计,不直接对块设备直接操作
块设备本身读写非常不灵活,是按块读写的,而内存是按字节单位操作的,而且可以随机操作,很灵活。
二、文件打开及创建
2.1 打开文件操作
使用函数open
其中open的返回值文件描述符很重要
2.2 open的参数说明
int open (const char *pathname,int flags);
int open (const char *pathname,int flags,mode_t mode);
其中pathname:要打开的文件名(包含路径,缺省为当前路径)
Flags:
O_RDONLY(只读打开) O_WRONLY(只写打开) O_RDWR(可读可写打开)
以上三个常数中应当只指定一个,当我们附带了权限之后,打开的文件就只能按照这种权限来操作。
下列常数是可选择的:
(1)O_CREAT 若文件不存在则创建它。使用此选项时,需要同时说明第三个参数 mode ,用其说明该新文件的存取许可权
(2)O_EXCL 如果同时指定了 OCREAT ,而文件已经存在,则出错。
(3)O_APPEND 每次写时都加到文件的尾端。
(4)O_TRUNC 属性去打开文件时,如果这个文件中本来是有内容的,而且为只读或只写成功打开,则将其长度截短为 0。Mode:一定是在flags中使用了O_CREAT标志,mode记录待创建的文件访问权限
2.3 文件操作可用的打开方式
O_RDONLY 只读打开
O_WRONLY 只写打开
O_RDWR 可读可写打开
//打开文件操作
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
int fd;
fd = open("./file1",O_RDWR) //O_RDWR可读可写
printf("fd = %d\n",fd);
retrun 0;
}
2.4 创建文件creat函数
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int fd;
char *buf = "test";
//int creat(const char *pathname, mode_t mode);
fd = creat("file2",S_IRWXU);
return 0;
}
filename:创建的文件名(包含路径、缺省为当前路径)
mode:创建模式 //可读可写可执行
常见创建模式:
宏表示 | 数字 | |
S_IRUSR | 4 | 可读 |
S_IWUSR | 2 | 可写 |
S_IXUSR | 1 | 可执行 |
S_IRWXU | 7 | 可读、可写、执行 |
2.5、写入文件操作
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main()
{
int fd;
char *buf = "xiao luo henshuai!";
fd = open("./file1",O_RDWR);
if(fd == -1){
printf("open file1 failed\n");
fd = open("./flie1",O_RDWR|O_CREAT,0600);
if(fd > 0){
printf("create file1 susceess!\n");
}
}
printf("open susceess : fd = %d\n",fd);
// ssize_t write(int fd, const void *buf, size_t count);
write(fd,buf,strlen(buf));
close(fd);
return 0;
}
2.6、读取文件操作
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main()
{
int fd;
char *buf = "xiao luo henshuai!";
fd = open("./file1",O_RDWR);
if(fd == -1){
printf("open file1 failed\n");
fd = open("./flie1",O_RDWR|O_CREAT,0600);
if(fd > 0){
printf("create file1 susceess!\n");
}
}
printf("open susceess : fd = %d\n",fd);
//ssize_t read(int fd, void *buf, size_t count);
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;
}
2.7、文件光标的位置
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main()
{
int fd;
char *buf = "xiao luo henshuai!";
fd = open("./file1",O_RDWR);
if(fd == -1){
printf("open file1 failed\n");
fd = open("./flie1",O_RDWR|O_CREAT,0600);
if(fd > 0){
printf("create file1 susceess!\n");
}
}
printf("open susceess : fd = %d\n",fd);
// ssize_t write(int fd, const void *buf, size_t count);
int n_write = write(fd,buf,strlen(buf));
if(n_write != -1){
printf("write %d byte to file\n",n_write);
}
//ssize_t read(int fd, void *buf, size_t count);
char *readBuf;
readBuf = (char *)malloc(sizeof(char)*n_write+1);
//off_t lseek(int fd, off_t offset, int whence);
lseek(fd,0,SEEK_SET);
int n_read = read(fd,readBuf,n_write);
printf("read:%d,context:%s\n",n_read,readBuf);
close(fd);
return 0;
}
三、文件编程练习demo
3.1 文件编程小应用-修改程序的配置文件
/*
linux系统编程-文件编程
文件编程小应用-修改程序的配置文件
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
int fdSrc;
char *readBuf = NULL;
if(argc != 2){
printf("pararm error\n");
exit(-1);
}
fdSrc = open(argv[1],O_RDWR);
int size = lseek(fdSrc,0,SEEK_END);
lseek(fdSrc,0,SEEK_SET);
readBuf = (char*)malloc(sizeof(char)*size + 8);
int n_read = read(fdSrc,readBuf,size);
//找到位置
char *p = strstr(readBuf,"LENG=");
if(p==NULL){
printf("not found\n");
exit(-1);
}
p = p+strlen("LENG=");
*p = '5';
lseek(fdSrc,0,SEEK_SET);
int n_write = write(fdSrc,readBuf,strlen(readBuf));
close(fdSrc);
return 0;
}
3.2、写一个整数文件
/*
linux系统编程-文件编程
写一个整数文件
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int fd;
int data = 100;
int data2 = 1;
fd = open("./file1",O_RDWR);
int n_write;
n_write = write(fd,&data,sizeof(int));
int n_read;
n_read = read(fd,&data,sizeof(int));
printf("read:%d\n",data2);
close(fd);
return 0;
}
3.3 写一个整数文件,写入一个结构体
/*
linux系统编程-文件编程
写一个整数文件,写入一个结构体
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
struct Test
{
int a;
char c;
};
int main()
{
int fd;
struct Test data[2] = {{100,'a'},{101,'b'}};
struct Test data2[2];
fd = open("./file1",O_RDWR);
int n_write;
n_write = write(fd,&data,sizeof(struct Test)*2);
int n_read;
n_read = read(fd,&data2,sizeof(struct Test)*2);
printf("read:%d,%c\n",data2[0].a,data2[0].c);
printf("read:%d,%c\n",data2[1].a,data2[1].c);
close(fd);
return 0;
}
3.4 linux cp 命令代码练习
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
int fdSrc;
int fdDes;
char *readBuf = NULL;
if(argc != 3){
printf("pararm error\n");
exit(-1);
}
fdSrc = open(argv[1],O_RDWR);
int size = lseek(fdSrc,0,SEEK_END);
lseek(fdSrc,0,SEEK_SET);
readBuf = (char*)malloc(sizeof(char)*size + 8);
int n_read = read(fdSrc,readBuf,size);
fdDes = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0600);
int n_write = write(fdDes,readBuf,strlen(readBuf));
close(fdSrc);
close(fdDes);
return 0;
}
四、用标准C库对文件进行操作
4.1 标准C库打开创建文件 读写文件 光标移动
//标准C库打开创建文件 读写文件 光标移动
#include <stdio.h>
#include <string.h>
int main()
{
//FILE *fopen(const char *path, const char *mode);
FILE *fd;
fd = fopen("./xiaoluo.txt","w+");
//size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
char *str = "xiaoluohenshuai";
fwrite(str,sizeof(char),strlen(str),fd);
fwrite(str,sizeof(char)*strlen(str),1,fd);
//int fseek(FILE *stream, long offset, int whence);
fseek(fd,0,SEEK_SET);
//size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
char readstr[128] = {0};
fread(readstr,sizeof(char),strlen(str),fd);
printf("read data: %s\n",readstr);
return 0;
}
4.2 标准C库写入结构体到文件
//标准C库写入结构体到文件
#include <stdio.h>
#include <string.h>
struct Test
{
int a;
char c;
};
int main()
{
//FILE *fopen(const char *path, const char *mode);
FILE *fd;
struct Test data = {100,'a'};
struct Test data2;
fd = fopen("./xiaoluo(1).txt","w+");
//size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
int n_fwrite;
n_fwrite = fwrite(&data,sizeof(struct Test),1,fd);
//int fseek(FILE *stream, long offset, int whence);
fseek(fd,0,SEEK_SET);
//size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
int n_fread;
n_fread = fread(&data2,sizeof(struct Test),1,fd);
printf("read data:%d,%c\n",data.a,data.c);
printf("read data2: %d,%c\n",data2.a,data2.c);
fclose(fd);
return 0;
}