文件操作
FILE结构体以及缓冲区深入探讨
FILE 结构体简介
由于不同的编译器对FILE结构体类型的实现方案不同 在此仅以vs 2012 stdio.h中的FILE结构体为例:
struct _iobuf{
char* _ptr;//指向缓冲区读写数据的位置信息
int _cnt;//"W":缓冲区剩余字节大小,“r”:数据写入缓冲区的字节大小
char* _base;//指向缓冲区的基地址
int _flag;//状态标志
int _file;//文件类型
int _charbuf;//
int _bufsize;//缓冲区的大小
char* _tmpfname;//临时文件名
};
typedef struct _iobuf FILE;
缓冲区
待完成!!!
文本文件和二进制文件到底有什么区别
文本文件和二进制文件的区别
-
文本文件文件通常用来保存肉眼可见的内容,例如:.txt、.c、.dat等文件,我们通过文本编辑器打开这些文件,可以看懂文件的内容。
-
二进制文件通常用来保存视频、图片、程序等内容,用文本编辑器打开这些文件,你将会看到一堆乱码。
但从物理存储的本质上是相同,都是二进制编码,我们之所以能看懂文本文件的内容,是因为文本文件中采用的是 ASCII、UTF-8、GBK 等字符编码,文本编辑器可以识别出这些编码格式,并将编码值转换成字符展示出来。
而二进制文件使用的是 mp4、gif、exe 等特殊编码格式,文本编辑器并不认识这些编码格式,只能按照字符编码格式胡乱解析,所以就成了一堆乱七八糟的字符,有的甚至都没见过。
总的来说,文件作为信息的载体,我们要知道他的存储类型并以正确的形式来解读它才能得到有用的信息。
fopen() 中的文本方式和二进制方式(Windows系统和Linux的文本文件换行符)
文本文件和二进制文件并无本质的区别,只是对于换行符号的处理不同。
C语言程序将\n作为换行符,类 UNIX/Linux 系统在处理文本文件时也将\n作为换行符,所以程序中的数据会原封不动地写入文本文件中,反之亦然。
但是 Windows 系统却不同,它将\r\n作为文本文件的换行符。
-
在 Windows 系统中,如果以文本方式打开文件,当读取文件时,程序会将文件中所有的r\n转换成一个字符\n。也就是说,如果文本文件中有连续的两个字符是\r\n,则程序会丢弃前面的\r,只读入\n。
-
当写入文件时,程序会将\n转换成\r\n写入。也就是说,如果要写入的内容中有字符\n,则在写入该字符前,程序会自动先写入一个\r。
因此,如果用文本方式打开二进制文件进行读写,读写的内容就可能和文件的内容有出入。
总起来说,对于 Windows 平台,为了保险起见,我们最好用"t"来打开文本文件,用"b"来打开二进制文件。对于 Linux 平台,使用"t"还是"b"都无所谓,既然默认是"t",那我们什么都不写就行了。
C语言实行getFileSize
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
int main() {
FILE* fp = fopen("test.txt", "r");
fseek(fp, 0, SEEK_END);
int len = ftell(fp);
rewind(fp);
fclose(fp);
printf("文件的长度为:%d", len);//文件中有 0D 0A
return 0;
}
C语言实现my_cp
在C语言输入/输出流和文件操作【一】 一文给出了my_cp但是未考虑周全复制的效率较低下,在此将实现高效的文件复制。
实现文件复制的主要思路是:开辟一个缓冲区不断的从文件中读入数据到缓冲区中,每当读完一次数据便把缓冲区的数据一次性写入到新的文件中,直到源文件的内容全部被读取。
两个关键的问题:
- 要开辟多大的缓冲区?
- 缓冲区无结束标志,如果缓冲区未满,如何确定写入的字节数目?
- 目前大部分的磁盘的扇区都是4K对齐的,如果写入的数据不是4K的整数倍就会跨扇区读取,降低效率,因此开辟4K的缓冲区。
- 每次读取都返回读取到的字节数。
#include<stdio.h>
#include<stdlib.h>
int main(int arg ,char* argv[]){
if(arg!=3){
puts("input error");
exit(0);
}
FILE * fpr = fopen(argv[1],"rb");
if(fpr == NULL){
puts("file open error");
exit(0);
}
FILE * fpw = fopen(argv[2],"wb");
if(fpw == NULL ){
puts("file open error");
exit(0);
}
int readSize = 1024 * 4;
char* readData = (char*) malloc(readSize);
if(readData == NULL){
puts("malloc error");
exit(0);
}
int realReadSize;
while((realReadSize = fread(readData,1,readSize,fpr))>0){
fwrite(readData,realReadSize,1,fpw);
}
free(readData);
fclose(fpr);
fclose(fpw);
return 0;
}
// Linux Ubantu 20.4
// gcc -o my_cp main.c
// ./my_cp sorceFileName newFileName
C语言实现文件插入、删除、更改
待完成!!!