Linux系统编程——文件编程
1.文件概述
操作API完成自动化操作。
2.文件打开及创建
注意包含头文件:
#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);
open()返回一个文件描述符
2.1打开文件open(关键:返回文件描述符)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
int fd;
fd = open("./file1",O_RDWR); //打开文件file1
printf("%d\n",fd); //打印返回文件描述符符号,-1为打开失败
return 0;
}
2.2创建并且打开文件 O_CREAT
#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 file1 failed\n");
fd = open("./file1",O_RDWR|O_CREAT,0600); //0_CREAT创建文件 0600:权限可读可写
if(fd > 0){
printf("%d\n",fd);
}
}
return 0;
}
-rw------- -:普通文件 rw:可读可写
2.3 O_EXCL可用来判断文件是否存在(配合O_CREAT使用)
#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);// O_EXCL判断文件是否存在
if(fd == -1){
printf("create file1 failed\n");
}
return 0;
}
输出结果(当文件存在时)
2.4 O_APPEND
#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 = "this is buf";
fd = open("./file1",O_RDWR|O_APPEND); //O_APPEND在文件末尾后添加内容
int n_write = write(fd,buf,strlen(buf));
if(n_write != -1){
printf("write sizeof:%d\n ",n_write);
}
lseek(fd,0,SEEK_SET);
char *readbuf;
readbuf = (char *)malloc(sizeof(char) * n_write);
int n_read = read(fd,readbuf,100);
printf("read sizeof:%d ,context :%s\n",n_read,readbuf);
close(fd);
return 0;
}
结果输出:
程序运行前:
程序运行后:
若不加O_APPEND:会覆盖原有内容
2.5 O_TRUNC(擦除原有内容,重新写入)
#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 = "this is buf";
fd = open("./file1",O_RDWR|O_TRUNC);//O_TRUNC(擦除原有内容,重新写入)
int n_write = write(fd,buf,strlen(buf));
if(n_write != -1){
printf("write sizeof:%d\n ",n_write);
}
lseek(fd,0,SEEK_SET);
char *readbuf; //野指针
readbuf = (char *)malloc(sizeof(char) * n_write);//开辟空间
int n_read = read(fd,readbuf,100);
printf("read sizeof:%d ,context :%s\n",n_read,readbuf);
close(fd);
return 0;
}
输出结果:
程序运行前:
程序运行后:
2.6 creat创建文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rRZxS6hE-1681889538374)(C:\Users\passersby\AppData\Roaming\Typora\typora-user-images\image-20230312113922534.png)]
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
int fd;
fd = creat("./file2",S_IRWXU);//S_IRWXU 可读可写可执行
return 0;
}
输出结果:
3.文件写入操作编程
注意包含头文件:
#include <unistd.h>
函数原形:
ssize_t write(int fd, const void *buf, size_t count);//从 void *buf 中读取 size_t count 个字节放入 int fd 返回写入的字节
使用:
#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 = "this is buf";
fd = open("./file1",O_RDWR);
if(fd == -1){
printf("open file1 failed\n");
fd = open("./file1",O_RDWR|O_CREAT,0600);
if(fd > 0){
printf("create file1 success! fd:%d\n",fd);
}
}
write(fd,buf,strlen(buf)); // write(fd,buf,sizeof(buf)); Linux下只会显示8个字符 sizeof计算的是指针的长度,要用strlen
close(fd);
return 0;
}
4.文件读取操作
注意包含头文件:
#include <unistd.h>
函数原形:
ssize_t read(int fd, const void *buf, size_t count);//从 fd 中读取 size_t count 个字节放入 void *buf
使用:
#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 = "this is buf";
fd = open("./file1",O_RDWR);
if(fd == -1){
printf("open file1 failed\n");
fd = open("./file1",O_RDWR|O_CREAT,0600);
if(fd > 0){
printf("create file1 success! fd:%d\n",fd);
}
}
int n_write = write(fd,buf,strlen(buf));
if(n_write != -1){
printf("write sizeof:%d ",n_write);
}
char *readbuf;
readbuf = (char *)malloc(sizeof(char) * n_write);
int n_read = read(fd,readbuf,n_write + 1);
printf("read sizeof:%d ,context :%s\n",n_read,readbuf);
close(fd);
return 0;
}
结果:
读取到 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 = "this is buf";
fd = open("./file1",O_RDWR);
if(fd == -1){
printf("open file1 failed\n");
fd = open("./file1",O_RDWR|O_CREAT,0600);
if(fd > 0){
printf("create file1 success! fd:%d\n",fd);
}
}
int n_write = write(fd,buf,strlen(buf));
if(n_write != -1){
printf("write sizeof:%d\n ",n_write);
}
close(fd);
open("./file1",O_RDWR);
char *readbuf;
readbuf = (char *)malloc(sizeof(char) * n_write);
int n_read = read(fd,readbuf,n_write + 1);
printf("read sizeof:%d ,context :%s\n",n_read,readbuf);
close(fd);
return 0;
}
输出结果:
5.文件光标移动操作
注意包含头文件:
#include <sys/types.h>
#include <unistd.h>
函数原形:
off_t lseek(int fd, off_t offset, int whence);// off_t offset:偏移值 负数往前偏移,正数往后偏移 whence :位置 返回文件从头到尾偏移值
SEEK_SET //头
SEEK_CUR //当前位置
SEEK_END //尾
使用:
#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 = "this is buf";
fd = open("./file1",O_RDWR);
if(fd == -1){
printf("open file1 failed\n");
fd = open("./file1",O_RDWR|O_CREAT,0600);
if(fd > 0){
printf("create file1 success! fd:%d\n",fd);
}
}
int n_write = write(fd,buf,strlen(buf));
if(n_write != -1){
printf("write sizeof:%d\n ",n_write);
}
// close(fd);
// open("./file1",O_RDWR)
char *readbuf;
readbuf = (char *)malloc(sizeof(char) * n_write);
// lseek(fd,0,SEEK_SET);
lseek(fd,-n_write,SEEK_END); //off_t offset:偏移值 负数往前偏移,正数往后偏移
int n_read = read(fd,readbuf,n_write + 1);
printf("read sizeof:%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>
#include <string.h>
#include <stdlib.h>
int main()
{
int fd;
char *buf = "this is buf";
fd = open("./file1",O_RDWR|O_CREAT,0600);
int n_write = write(fd,buf,strlen(buf));
int fileSize = lseek(fd,0,SEEK_END);
printf("file1 sizeof:%d\n",fileSize);
close(fd);
return 0;
}
6.文件打开创建的补充
已补充到[2.2、2.3、2.4、2.5](#2.2创建并且打开文件 O_CREAT)
7.文件操作原理
文件描述符(非负整数) = open(文件,)
Linux系统中默认:
0 | 1 | 2 |
---|---|---|
标准输入 | 标准输出 | 标准错误 |
使用:
#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 readbuf[128];
//ssize_t read(int fd, const void *buf, size_t count);//从 fd 中读取 size_t count 个字节放入 void *buf
int n_read = read(1,readbuf,5);
int n_write = write(0,readbuf,strlen(readbuf));
return 0;
}
静态文件 | 动态文件 |
---|---|
文件存在磁盘中 | open静态文件后,会在Linux内核产生结构体记录 |
read,write都是对动态文件进行操作,调用close,将缓存区存入磁盘
8.文件操作小应用之实现cp指令
参数 cp src.c des.c
0 | 1 | 2 |
---|---|---|
cp | src.c | des.c |
argv[0] | argv[1] | argv[2] |
argv[ ] :字符串数组
-
C语言参数
-
思路
- 打开src.c
- 读src到buf
- 打开/创建des.c
- 将buf写入到des.c
- 关闭两个文件
测试:
#include <stdio.h>
int main(int argc,char **argv)
{
printf("total params:%d",agrc);
printf("No.1 params:%d",agrv[0]);
printf("No.2 params:%d",agrv[1]);
printf("No.3 params:%d",agrv[2]);
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 argc,char **argv)
{
if(argc != 3){
printf("params error\n");
exit(-1);
}
int fdSrc;
int fdDes;
//char readbuf[1024]; //直接定义大小会造成空间浪费或者不够用
char *readbuf = NULL; //缓冲区
fdSrc = open(argv[1],O_RDWR);
int fdSrcSize = lseek(fdSrc,0,SEEK_END); //获取被拷贝文件大小
lseek(fdSrc,0,SEEK_SET); //将光标重新定位到文件头
readbuf = (char *)malloc(sizeof(char)*fdSrcSize+8); //根据需要拷贝文件大小来开辟空间
int n_read = read(fdSrc,readbuf,fdSrcSize); //从源文件读取内容到缓冲区
fdDes = open(argv[2],O_RDWR|O_CREAT,0600); //打开/创建目标文件
int n_write = write(fdDes,readbuf,strlen(readbuf)); //将缓冲区内容拷贝到目标文件
close(fdSrc); //关闭源文件
close(fdDes); //关闭目标文件,此时为静态文件放入磁盘中
return 0;
}
9.解决拷贝的一些bug
#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 argc,char **argv)
{
if(argc != 3){
printf("params error\n");
exit(-1);
}
int fdSrc;
int fdDes;
//char readbuf[1024]; //直接定义大小会造成空间浪费或者不够用
char *readbuf = NULL; //缓冲区
fdSrc = open(argv[1],O_RDWR);
int fdSrcSize = lseek(fdSrc,0,SEEK_END); //获取被拷贝文件大小
lseek(fdSrc,0,SEEK_SET); //将光标重新定位到文件头
readbuf = (char *)malloc(sizeof(char)*fdSrcSize+8); //根据需要拷贝文件大小来开辟空间
int n_read = read(fdSrc,readbuf,fdSrcSize); //从源文件读取内容到缓冲区
fdDes = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0600); //打开/创建目标文件,如果目标文件存在由内容就要使用O_TRUNC擦除原来内容,重新写入
int n_write = write(fdDes,readbuf,strlen(readbuf)); //将缓冲区内容拷贝到目标文件
close(fdSrc); //关闭源文件
close(fdDes); //关闭目标文件,此时为静态文件放入磁盘中
return 0;
}
10.文件编程小应用之修改程序的配置文件
思路:
- 找到需要修改的位置
- 位置往后移
- 修改参数
strstr函数
STRSTR(3) Linux Programmer's Manual STRSTR(3)
NAME
strstr, strcasestr - locate a substring
SYNOPSIS
#include <string.h>
char *strstr(const char *haystack, const char *needle); //函数查找字符串haystack第一次出现的子串needle 。 终止'\ 0'字符不进行比较。
/*
参数 (Parameters)
haystack - 这是要扫描的主要C字符串。
needle - 这是用in-haystack字符串搜索的小字符串。
*/
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <string.h>
char *strcasestr(const char *haystack, const char *needle);
DESCRIPTION
The strstr() function finds the first occurrence of the substring
needle in the string haystack. The terminating null bytes ('\0') are
not compared.
The strcasestr() function is like strstr(), but ignores the case of
both arguments.
RETURN VALUE
These functions return a pointer to the beginning of the substring,
or NULL if the substring is not found.//返回值 这些函数返回一个指向子字符串开头的指针,如果子字符串没有找到,则为NULL。(返回一个字符串开头的指针,指向查找字符的头部)
使用:
#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 argc,char **argv)
{
if(argc != 2){
printf("params error\n");
exit(-1);
}
int fdSrc;
char *readbuf = NULL;
fdSrc = open(argv[1],O_RDWR);
int fdSrcSize = lseek(fdSrc,0,SEEK_END); //用lseek计算文件大小
lseek(fdSrc,0,SEEK_SET); //将光标重新定位到文件头
readbuf = (char *)malloc(sizeof(char)*fdSrcSize+8); //根据计算到的文件大小来开辟空间,避免空间的浪费
int n_read = read(fdSrc,readbuf,fdSrcSize); //将文件内容读取到
char *p = strstr(readbuf,"LENG="); //在 readbu 字符串中查找第一次出现"LENG="的位置
if( p == NULL){
printf("No found\n");
exit(-1);
}
p = p + strlen("LENG="); //p承接的是strstr函数的返回值;返回一个字符串指针,并且指向第一次查找到字符串的头;p = p+strlen("LENG="),将位置偏移到 = 后.
*p='5'; //修改参数
int n_write = write(fdSrc,readbuf,strlen(readbuf)); //重新写入参数
close(fdSrc);
return 0;
}
程序运行前:
程序运行后:
bug:会发现与所想的不一样(因为光标在文件末尾)
优化解决:
- 将光标重新定位到文件头
- 使用O_TRUNC
①优化实现思路一:
#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 argc,char **argv)
{
if(argc != 2){
printf("params error\n");
exit(-1);
}
int fdSrc;
char *readbuf = NULL;
fdSrc = open(argv[1],O_RDWR);
int fdSrcSize = lseek(fdSrc,0,SEEK_END);
lseek(fdSrc,0,SEEK_SET);
readbuf = (char *)malloc(sizeof(char)*fdSrcSize+8);
int n_read = read(fdSrc,readbuf,fdSrcSize);
char *p = strstr(readbuf,"LENG="); //在 readbu 字符串中查找第一次出现"LENG="的位置
if( p == NULL){
printf("No found\n");
exit(-1);
}
p = p + strlen("LENG="); //p承接的是strstr函数的返回值;返回一个字符串指针,并且指向第一次查找到字符串的头;p = p+strlen("LENG="),将位置偏移到 = 后.
*p='5'; //修改参数,要注意是字符!!
lseek(fdSrc,0,SEEK_SET); //将光标重新定位到文件头;
int n_write = write(fdSrc,readbuf,strlen(readbuf)); //重新写入参数
close(fdSrc);
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 argc,char **argv)
{
if(argc != 2){
printf("params error\n");
exit(-1);
}
int fdSrc;
char *readbuf = NULL;
fdSrc = open(argv[1],O_RDWR);
int fdSrcSize = lseek(fdSrc,0,SEEK_END);
lseek(fdSrc,0,SEEK_SET);
readbuf = (char *)malloc(sizeof(char)*fdSrcSize+8);
int n_read = read(fdSrc,readbuf,fdSrcSize);
char *p = strstr(readbuf,"LENG="); //在 readbu 字符串中查找第一次出现
"LENG="的位置
if( p == NULL){
printf("No found\n");
exit(-1);
}
p = p + strlen("LENG="); //p承接的是strstr函数的返回值;返回一个字符
串指针,并且指向第一次查找到字符串的头;p = p+strlen("LENG="),将位置偏移到 = 后.
*p='5'; //修改参数
// lseek(fdSrc,0,SEEK_SET); //将光标重新定位到文件头;
close(fdSrc);
fdSrc = open(argv[1],O_RDWR|O_TRUNC); //重新打开文件,并擦除原有内容
int n_write = write(fdSrc,readbuf,strlen(readbuf)); //重新写入参数
close(fdSrc);
return 0;
}
程序运行后:(结果也是可以的)
11.写一个整数到文件
使用:
#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 argc,char **argv)
{
int fdSrc;
int data = 100;
int data2 = 0;
fdSrc = open("./file2",O_RDWR|O_CREAT);
//ssize_t write(int fd, const void *buf, size_t count);//从 void *buf 中读取 size_t count 个字节放入 int fd 返回写入的字节
int n_write = write(fdSrc,&data,sizeof(int));
lseek(fdSrc,0,SEEK_SET);
int n_read = read(fdSrc,&data2,sizeof(int));
printf("read:%d\n",data2);
close(fdSrc);
return 0;
}
结果:
人所看见是乱码,但不影响计算机实际读取
tips:发现一个有趣的现象
fdSrc = open("./file2",O_RDWR|O_CREAT);
“./file2”,我写成了".file2",没有生成file2文件,这很正常,但也能读出结果。目前我认为这一切都是在缓冲区运行的,并没有直接读取
12.写结构体数组到文件
结构体写入文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
struct Test
{
int data;
char c;
};
int main(int argc,char **argv)
{
int fdSrc;
struct Test data = {200,'b'};
struct Test data2;
fdSrc = open("./file2",O_RDWR);
int n_write = write(fdSrc,&data,sizeof(struct Test)); //重新写入参数
lseek(fdSrc,0,SEEK_SET);
int n_read = read(fdSrc,&data2,sizeof(struct Test ));
printf("read:%d,%c\n",data2.data,data2.c);
close(fdSrc);
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>
struct Test
{
int data;
char c;
};
int main(int argc,char **argv)
{
int fdSrc;
struct Test data[2] = {{100,'a'},{200,'b'}};
struct Test data2[2];
fdSrc = open("./file2",O_RDWR);
int n_write = write(fdSrc,&data,sizeof(struct Test)*2); //重新写入参数 用链表要另作算法,这是数组,读的块
lseek(fdSrc,0,SEEK_SET);
int n_read = read(fdSrc,&data2,sizeof(struct Test )*2);
printf("read:%d,%c\n",data2[0].data,data2[0].c);
printf("read:%d,%c\n",data2[1].data,data2[1].c);
close(fdSrc);
return 0;
}
13.标准C库对文件操作引入
1.来源
-
open
是UNIX系统调用函数(包括LINUX等),返回的是文件描述符(File Descriptor),它是文件在文件描述符表里的索引。` -
fopen
是ANSIC标准中的C语言库函数,在不同的系统中应该调用不同的内核api。返回的是一个指向文件结构的指针。
2.移植性
fopen
是C标准函数,因此拥有良好的移植性;而open
是UNIX系统调用,移植性有限。
3.适用范围
-
open
返回文件描述符,而文件描述符是UNIX系统下的一个重要概念,UNIX下的一切设备都是以文件的形式操作。如网络套接字、硬件设备等。当然包括操作普通正规文件(Regular File)。 (一些特定条件(进程间的通行,管道)下必须用
open`打开) -
fopen
是用来操纵普通正规文件(Regular File)的
4.文件IO层次
如果从文件IO的角度来看,前者属于低级IO函数,后者属于高级IO函数。低级和高级的简单区分标准是:谁离系统内核更近。低级文件IO运行在内核态,高级文件IO运行在用户态。
5. 缓冲
1.缓冲文件系统
缓冲文件系统的特点是:在内存开辟一个“缓冲区”,为程序中的每一个文件使用;当执行读文件的操作时,从磁盘文件将数据先读入内存“缓冲区”,装满后再从内存“缓冲区”依此读出需要的数据。执行写文件的操作时,先将数据写入内存“缓冲区”,待内存“缓冲区”装满后再写入文件。由此可以看出,内存“缓冲区”的大小,影响着实际操作外存的次数,内存“缓冲区”越大,则操作外存的次数就少,执行速度就快、效率高。一般来说,文件“缓冲区”的大小随机器 而定。fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind
等。
2.非缓冲文件系统
缓冲文件系统是借助文件结构体指针来对文件进行管理,通过文件指针来对文件进行访问,既可以读写字符、字符串、格式化数据,也可以读写二进制数据。非缓冲文件系统依赖于操作系统,通过操作系统的功能对文件进行读写,是系统级的输入输出,它不设文件结构体指针,只能读写二进制文件,但效率高、速度快,由于ANSI标准不再包括非缓冲文件系统,因此建议大家最好不要选择它。open, close, read, write, getc, getchar, putc, putchar
等。
一句话总结一下,就是open
无缓冲,fopen
有缓冲。前者与read
, write
等配合使用, 后者与fread
,fwrite
等配合使用。
使用fopen
函数,由于在用户态下就有了缓冲,因此进行文件读写操作的时候就减少了用户态和内核态的切换(切换到内核态调用还是需要调用系统调用API:read
,write
);而使用open
函数,在文件读写时则每次都需要进行内核态和用户态的切换;表现为,如果顺序访问文件,fopen
系列的函数要比直接调用open
系列的函数快;如果随机访问文件则相反。
14.标准C库打开创建文件读写光标移动
1.fopen函数
FOPEN(3) Linux Programmer's Manual FOPEN(3)
NAME
fopen, fdopen, freopen - stream open functions
SYNOPSIS
#include <stdio.h>
FILE *fopen(const char *path, const char *mode);//常用 参数:文件地址 权限
FILE *fdopen(int fd, const char *mode);
FILE *freopen(const char *path, const char *mode, FILE *stream);
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
fdopen(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE
参数说明
参数mode字符串包含了文件访问模式,欲打开的文件路径及文件名,参数 mode 字符串则代表着流形态。
mode 有下列几种形态字符串:
字符串 | 说明 |
---|---|
r | 以只读方式打开文件,该文件必须存在。 |
r+ | 以读/写方式打开文件,该文件必须存在。 |
rb+ | 以读/写方式打开一个二进制文件,只允许读/写数据。 |
rt+ | 以读/写方式打开一个文本文件,允许读和写。 |
w | 打开只写文件,若文件存在则文件长度清为零,即该文件内容会消失;若文件不存在则创建该文件。 |
w+ | 打开可读/写文件,若文件存在则文件长度清为零,即该文件内容会消失;若文件不存在则创建该文件。 |
a | 以附加的方式打开只写文件。若文件不存在,则会创建该文件;如果文件存在,则写入的数据会被加到文件尾后,即文件原先的内容会被保留(EOF 符保留)。 |
a+ | 以附加方式打开可读/写的文件。若文件不存在,则会创建该文件,如果文件存在,则写入的数据会被加到文件尾后,即文件原先的内容会被保留(EOF符不保留)。 |
wb | 以只写方式打开或新建一个二进制文件,只允许写数据。 |
wb+ | 以读/写方式打开或新建一个二进制文件,允许读和写。 |
wt+ | 以读/写方式打开或新建一个文本文件,允许读和写。 |
at+ | 以读/写方式打开一个文本文件,允许读或在文本末追加数据。 |
ab+ | 以读/写方式打开一个二进制文件,允许读或在文件末追加数据。 |
2.fwrite函数 & fread函数
FREAD(3) Linux Programmer's Manual FREAD(3)
NAME
fread, fwrite - binary stream input/output
SYNOPSIS
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);//从 FILE *stream 读内容到void *ptr
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);//从void *ptr读取内容写到FILE *stream
//size_t size:大小 size_t nmemb:写几次
DESCRIPTION
The function fread() reads nmemb elements of data, each size bytes
long, from the stream pointed to by stream, storing them at the loca‐
tion given by ptr.
The function fwrite() writes nmemb elements of data, each size bytes
long, to the stream pointed to by stream, obtaining them from the
location given by ptr.
For nonlocking counterparts, see unlocked_stdio(3).
3.fseek函数
使用原理和lseek类似
FSEEK(3) Linux Programmer's Manual FSEEK(3)
NAME
fgetpos, fseek, fsetpos, ftell, rewind - reposition a stream
SYNOPSIS
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
long ftell(FILE *stream);
void rewind(FILE *stream);
int fgetpos(FILE *stream, fpos_t *pos);
int fsetpos(FILE *stream, fpos_t *pos);
4.fclose函数
FCLOSE(3) Linux Programmer's Manual FCLOSE(3)
NAME
fclose - close a stream
SYNOPSIS
#include <stdio.h>
int fclose(FILE *fp);
DESCRIPTION
The fclose() function flushes the stream pointed to by fp (writing
any buffered output data using fflush(3)) and closes the underlying
file descriptor.
The behaviour of fclose() is undefined if the stream parameter is an
illegal pointer, or is a descriptor already passed to a previous
invocation of fclose().
RETURN VALUE
Upon successful completion 0 is returned. Otherwise, EOF is returned
and the global variable errno is set to indicate the error. In
either case any further access (including another call to fclose())
to the stream results in undefined behavior.
使用:
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fp;
fp = fopen("aaaa.txt","w+"); //打开文件
char *p = "this is wang";
char readbuf[128]={"\0"};
int n_fwrite = fwrite(p,sizeof(char) * strlen(p),1,fp); // 从p读内容写到fp
// int n_fwrite = fwrite(p,sizeof(char),strlen(p),fp); // 从p读内容写到fp
fseek(fp,0,SEEK_SET);
int n_fread = fread(readbuf,sizeof(char) * strlen(p),1,fp);//从fp 读内容到readbuf
printf("readbuf:%s\n",readbuf);
fclose(fp);
return 0;
}
15.标准C库写入结构体到文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
struct Test
{
int a;
char c;
};
int main()
{
FILE *fp;
struct Test data = {100,'a'};
struct Test data2;
fp = fopen("./file1","w+");
int n_write = fwrite(&data,sizeof(struct Test),1,fp); //n_write=1 返回的是写的次数
fseek(fp,0,SEEK_SET);
int n_read = fread(&data2, sizeof(struct Test),1,fp);
printf("read %d,%c \n",data2.a,data2.c);
fclose(fp);
return 0;
}
16.文件其他函数讲解及文件到尾
函数原型:
NAME
fputc, fputs, putc, putchar, puts - output of characters and strings
SYNOPSIS
#include <stdio.h>
int fputc(int c, FILE *stream);
int fputs(const char *s, FILE *stream);
int putc(int c, FILE *stream);
int putchar(int c);
int puts(const char *s);
DESCRIPTION
fputc() writes the character c, cast to an unsigned char, to stream.
fputs() writes the string s to stream, without its terminating null
byte ('\0').
putc() is equivalent to fputc() except that it may be implemented as a
macro which evaluates stream more than once.
putchar(c); is equivalent to putc(c,stdout).
puts() writes the string s and a trailing newline to stdout.
Calls to the functions described here can be mixed with each other and
with calls to other output functions from the stdio library for the
same output stream.
For nonlocking counterparts, see unlocked_stdio(3).
RETURN VALUE
fputc(), putc() and putchar() return the character written as an
unsigned char cast to an int or EOF on error.
puts() and fputs() return a nonnegative number on success, or EOF on
error.
CONFORMING TO
C89, C99.
int feof(FILE *stream);
判断是否到文件尾巴,没到尾巴返回0;到尾巴返回非0;
使用:
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fp;
int i;
char *str = "write char inout!";
int len = strlen(str);
fp = fopen("./test.txt","w+");
for(i=0;i<len;i++){
// int fputc(int c, FILE *stream);
fputc(*str,fp);
str++;
}
fclose(fp);
return 0;
}
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fp;
int i;
char c;
fp = fopen("./test.txt","r");
while(!feof(fp)){// nonezero if reach end of file
c = fgetc(fp);
printf("%c",c);
}
fclose(fp);
return 0;
}