文件操作
程序运行产生的数据是存储在内存中的,当程序关闭的时候,数据随之丢失,想要保存数据,需要进行文件操作将数据保存在磁盘中。
在进行文件操作的时候,为了提高存取效率,程序在执行是会提供额外的内存暂时存放数据,这块内存就是缓冲区
例如写入文件时:
1FILE*fWrite;
2if (!(fWrite = fopen("test.txt", "w")))
3{
4 printf("file was not opened! ");
5 exit(1);
6}
7fputc('a');
在这里字符a只是写入到了缓冲区,并没有写入磁盘。当你关闭文件或者缓冲区已满的时候才会写入到磁盘当中,例如进行文件关闭:
1fclose(fWrite);
右键任意文件,点击属性,在位置那一栏里面可以找到该文件的绝对路径
注意!!! 注意!!! 注意!!!
1D:\test D盘下的text文件夹
2文件读取时要换成:
3D:\\test\\test.txt 两个\\是因为:单独一个\是转义,两个\\才代表'\'
4或者
5D:/test/test.txt 用这个是为了区分转义字符
相对路径是相对于工作空间而言的,在windows和Linux下
../ 表示上级目录
./ 表示当前目录
1fWrite = fopen("./test.txt", "w")); //表示当前文件夹下的test.txt文件 ./可忽略
2fWrite = fopen("../test.txt", "w")); //表示当前文件的上级目录下的test.txt文件
在程序打包过程中,如果出现程序运行什么都没有,一般是路径弄错了,导致程序找不到图片资源。
程序中一般用的是相对路径寻找文件
1FILE*fWrite, *fRead;
2//第一种打开文件的方法
3if (!(fWrite = fopen("test.txt", "w")))
4{
5 printf("file was not opened! ");
6 exit(1);
7}
8//第二种打开文件的方法
9fRead = fopen("test.txt", "r");
10if (fRead == NULL)
11{
12 printf("file was not opened! ");
13 exit(1);
14}
需要注意的是:
1"t":表示文本文件 rt 一般t可以省略不写
2"b":表示二进制文件 rb
3"+":表示文件可读写
4
5"r":只能从文件中读数据,该文件必须先存在,否则打开失败
6"w":只能向文件写数据,若指定的文件不存在则创建它,如果存在则先删除它再重建一个新文件
7"a":向文件增加新数据(不删除原有数据),若文件不存在则打开失败,打开时位置指针移到文件末尾
8"r+":可读/写数据,该文件必须先存在,否则打开失败
9"w+":可读/写数据,用该模式打开新建一个文件,先向该文件写数据,然后可读取该文件中的数据
10"a+":可读/写数据,原来的文件不被删去,位置指针移到文件末尾
1fclose(fRead);
2fclose(fWrite);
函数原型:
1int fputc(
2int c, //字符
3FILE *stream //文件指针
4);
1int fgetc(
2FILE *stream //文件指针
3);
程序示例:
1void function()
2{
3 //打开文件
4 FILE*fWrite, *fRead;
5 if (!(fWrite = fopen("./test.txt", "w")))
6 {
7 printf("file was not opened! ");
8 exit(1);
9 }
10 fRead = fopen("./test.txt", "r");
11 if (fRead == NULL)
12 {
13 printf("file was not opened! ");
14 exit(1);
15 }
16 /*************** fputc *****************/
17 //写入单个字符
18 fputc('a', fWrite); //写入字符
19 //循环写入字符
20 char arr[128] = "你好,世界!";
21 //for (int i = 0; i < strlen(arr); i++)
22 //{
23 // fputc(arr[i], fWrite);
24 //}
25 char *p = arr;
26 while ((*p != '\0') && fputc(*(p++), fWrite) != EOF);
27 fclose(fWrite); //一定要记得关闭文件
28 /*************** fgetc *****************/
29 //单个读取字符
30 char ch = fgetc(fRead);
31 putchar(ch);
32
33 rewind(fRead); //将文件内部指针移回文件开头
34 //循环读取字符
35 //for (int i = 0; (ch = fgetc(fRead)) != EOF; i++)
36 //{
37 // arr[i] = ch;
38 //}
39 //puts(arr);
40 while (!feof(fRead)) //feof函数
41 {
42 printf("%c", fgetc(fRead));
43 }
44 fclose(fRead);
45}
在Linux下看到的效果更明显:
1ubuntu@ubuntu:~/work$ ls
2main.c
3ubuntu@ubuntu:~/work$ gcc main.c -o main.exe
4ubuntu@ubuntu:~/work$ ls
5main.c main.exe
6ubuntu@ubuntu:~/work$ ./main.exe
7aa你好,世界!
8ubuntu@ubuntu:~/work$ ls
9main.c main.exe test.txt
我们可以明显的看到work/目录下在运行main.exe程序之后得到test.txt这个文件
注意:
函数原型:
1int fputs(
2 const char *str, //字符数组
3 FILE *stream //文件指针
4);
1char *fgets(
2 char *str, //字符数组
3 int numChars, //最多读取的字符个数
4 FILE *stream //文件指针
5);
示例:
1//写入
2fputs( "Hello world\n", fWrite);
3//读取
4char arr[128];
5while (fgets(arr, 127, fRead) != NULL) //arr至少留一个位置给'\0'
6{
7 puts(arr);
8}
函数原型:
1int fprintf(
2 FILE *stream, //文件指针
3 const char *format [,//字符数组
4 argument ]...
5);
1int fscanf(
2 FILE *stream, //文件指针
3 const char *format [,//字符数组
4 argument ]...
5);
这两个函数和printf,scnaf类似,示例如下
1//写入文件
2fprintf(fWrite, "我的学号是%d\n",1001);
3char arr[128]="你好,世界!";
4fprintf(fWrite,arr);
5//读取文件
6while (!feof(fRead))
7{
8 fscanf(fRead, arr);
9 puts(arr);
10}
函数原型:
1size_t fwrite(
2 const void *buffer, //指向要写入的数据的指针
3 size_t size, //要写入项目的大小,以字节为单位
4 size_t count, //要写入的最大项目数
5 FILE *stream //指向FILE结构的指针
6);
1size_t fread(
2 void *buffer, //数据的存储位置
3 size_t size, //项目大小(以字节为单位)
4 size_t count, //读取的最大项目数
5 FILE *stream //指向FILE结构的指针
6);
在读写结构体的时候强烈推荐这种的读写方式,简单,方便
示例:
1#include<stdio.h>
2typedef struct student
3{
4 int iId;
5 int iScore;
6}STU;
7int main()
8{
9 FILE*fWrite, *fRead;
10 if (!(fWrite = fopen("test3.dat", "wb")))
11 {
12 printf("file was not opened! ");
13 exit(1);
14 }
15 fRead = fopen("test3.dat", "rb");
16 if (fRead == NULL)
17 {
18 printf("file was not opened! ");
19 exit(1);
20 }
21 /*************** fwrite *****************/
22 STU stu = { 1001,100 };
23 fwrite(&stu //指向要写入的数据的指针
24 , sizeof(stu) //项目大小,以字节为单位
25 , 1 //要写入的最大项目数
26 , fWrite //指向FILE结构的指针
27 );
28 stu.iId = 1002;
29 fwrite(&stu //指向要写入的数据的指针
30 , sizeof(stu) //项目大小,以字节为单位
31 , 1 //要写入的最大项目数
32 , fWrite //指向FILE结构的指针
33 );
34 fclose(fWrite);
35 /*************** fread *****************/
36 rewind(fRead); //将文件内部指针移回文件开头
37 STU temp;
38 while (1)
39 {
40 fread(&temp //指向要写入的数据的指针
41 , sizeof(STU) //项目大小,以字节为单位。
42 , 1 //要写入的最大项目数
43 , fRead //指向FILE结构的指针
44 );
45 if (feof(fRead)) break;
46 printf("id:%d\tscore:%d\n", temp.iId, temp.iScore);
47 }
48 fclose(fRead);
49 return 0;
50}
也可以参考下学生信息管理系统里面的读写操作
使文件位置标志重新返回文件的开头
1rewind(fRead); //相当于你接下来读取的位置为fRead指向文件的开头位置
1int fseek(
2 FILE *stream, //指向FILE结构的指针
3 long offset, //从初始位置开始的字节数
4 int origin //初始位置
5);
其中origin设置有这三个宏
原始值 | 原值 | 含义 |
---|---|---|
SEEK_SET | 0 | 文件的开头 |
SEEK_CUR | 1 | 文件指针的当前位置 |
SEEK_END | 2 | 文件末尾 |
示例:
1fseek(fRead,sizeof(STU),SEEK_SET); //将文件指针移到开始位置sizeof(STU)字节处
1long ftell(
2 FILE *stream
3);
作用:得到文件标志的当前位置
示例:
1long index=ftell(fRead); //得到文件指针的位置