前言
文件操作的话,之前学过一点点 python 的话就会发现都挺像的
课堂
提到文件操作的话,C 语言里面就是记住这个函数指针就行—FILE*,咱们来看一下它在源码里面是个啥,其实就把它也看成一种数据类型就行,不过是起了个别名
这个是在 vc6 以及老版本的 vscode 里面是这样的,但我的 vs2019 是这么写的
这个里面封装好了很多的变量,这些变量就是写在 C 语言底层里面的一些功能需要用到的,不用理解,知道就行
fopen()
这个就是用来打开一个文件后,返回指向该文件首地址的地址指针
FILE* fp = fopen("文件名","打开模式");
比如:FILE* fp = fopen("C:\123\123.txt","r");
fclose()
用来关闭文件流
FILE* fp = fopen("d:\a.txt","w");
int n = fclose(fp);
这个n不用有的,但要知道这个函数是有返回值的,如果正常关闭则返回0;如果异常则返回EOF
fwrite()&fread()
这个就是相当于把硬盘文件上的东西写到内存,以及把内存中的东西写到硬盘文件上面
size_t fread(要读的内存指针,读的这内存大小,有几个这样的内存,文件指针); //从文件中读
size_t fwrite(要写的内存指针,写的这内存大小,有几个这样的内存,文件指针); //向文件中写
//如:假设已经定义好了一个Student结构体,一般是以一个结构体为单位的方式读写,自己定义大小也行
Student stu;
fread(&stu,sizeof(Student),1,fp);
//或者一直需要读取100字节数据到内存
char* mem = 某个内存起始地址;
fread(mem,100,1,fp);
返回值:成功读写的字节数
fseek()
这个就有点像 SQL 注入里面那个 sub 什么的,就是用来定位文件指针位置的函数,说白了就是控制指针变量步长的函数
int i = fseek(文件指针,偏移量,基准);
第一个参数fp为文件指针;
第二个参数是偏移量,表示要偏移的字节数,正数表示正向偏移,负数表示负向偏移;
第三个参数表示设定从文件的哪里开始偏移,取值为:0、1、2
为0:表示从文件起始位置增加 offset 个偏移量为新的读写位置
为1:表示从目前的读写位置增加 offset 个偏移量为新的读写位置
为2:表示从文件尾后,再增加 offset 个偏移量为新的读写位置
FILE* fp = fopen("d:\a.txt","wb"); //假设文件内容为abcd
int i = fseek(fp,sizeof(char)*2,0); //fp指向从a开始向后偏移2字节位置,即c。但是i的值为0
//或者 int i = fseek(fp,100L,1);
如果执行成功,返回值为0;如果执行失败,不改变 fp 指向的位置,函数的返回值为 -1
ftell()
使用 ftell 函数来取得当前文件的读写位置(是相对于传入的文件来说的相对位置,比如最开始 ftell 返回的值为 1),以字节为单位!
FILE* fp = fopen("d:\a.txt","rb"); //假如a.txt文件中的内容是123,即3字节
int start = ftell(fp); //最开始指向的位置应为1!!!
fseek(fp,0,2); //把fp移到文件尾
int size = ftell(fp); //此时size的值应该为3!!!而不是2!!一定要注意!所以可以用此方法算文件大小
fprintf()&fscanf()
-
fscanf:从文件指针中读取数据,存储到后面的参数中
-
fprintf:把后面的参数中的数据,存储到文件指针中去
-
每读或写完:文件指针都要向后偏移
fscanf(fp,"%d",&num); //第一个参数是文件指针,后面两个和scanf参数一样
//fprintf同理
作业
1.读文件到内存和 2.读内存到文件再打开,就是偷个懒一个程序写了两个功能
#include "stdafx.h"
#include <malloc.h>
#include <MEMORY.h>
int file_size_2(FILE* pf){
if (pf == NULL){
perror("打开文件错误");
return -1;
}
fseek(pf, 0, SEEK_END);
int length = ftell(pf);
fseek(pf,0,SEEK_SET);
return length;
}
/*把硬盘里的数据加载到内存*/
int read_file_2(){
FILE* pf;
FILE* pf2;
pf = fopen("C:\\Windows\\System32\\notepad.exe","rb");
pf2 = fopen("C:\\Windows\\System32\\111.exe","wb");
int length = file_size_2(pf);
char* ptr;
ptr = (char*)malloc(sizeof(char)*length);
if (ptr == NULL){
return 0;
}else{
memset(ptr,0,sizeof(char)*length);
}
fread(ptr,length,1,pf);
fwrite(ptr,length,1,pf2);
int addr = (int)ptr;
printf("%x",addr);
free(ptr);
fclose(pf);
fclose(pf2);
return addr;
}
3.找不同
-
在硬盘上的 exe 打开后首地址是从 0 开始的;但是正在运行时在内存中是从 0x1000000 开始的
-
还可以发现上面一大段都是相同的,直到出现了空白区,接着在硬盘上的文件的内容起始地址从向后偏移 0x400 的位置开始;但是正在运行时的文件的内容在内存中是从偏移 0x1000 的位置开始
-
如果再往后面找,发现又会出现断开的地方,就是空白区,一堆 00。再接着又是一大段数据。在硬盘上的文件空白区比运行时在内存中的空白区小,但是两者的结构都是惊人的相似
-
最后会发现硬盘上的文件总大小 < 运行时的大小,感觉运行时的文件向被拉伸了一样
具体的情况可以跟上上面的 4 点依次去试试