什么是文件
以二进制形式和字符形式存入电脑操作系统的文件就是文件
- 磁盘上的文件是磁盘文件,内存中的文件是内存文件,但是在程序设计中,我们一般谈的文件有两种:程序文件、数据文件。
- 文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件。
文件操作:
文件类型
- 将程序的数据(内存中)存在盘符里的过程、及将盘符的内存读取到内存的过程。
· 操作主要包括:读档和存档;
· 文件的路径:一般写相对路径;
· 二进制文件:用计算机方式存放的文件,后缀可以是任何格式(二进制文件用记事本打开的时候会乱码,但是保密性强),二进制文件计算机在读取的时候更快,适合编程使用,比如 mp3 ,wav;
· 文本文件就是用文本文件打开不会乱码的文件,不会乱码,但是保密性不强。 - 文件操作中的函数要注意是对文件进行操作,而不是对输出屏幕进行操作。
文件缓冲区
ANSIC标准采用“缓冲文件系统”处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根据C编译系统决定的。
文件指针
缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”。
- 在对文件进行操作前,要先打开函数-fopen
对文件进行写入时有以下函数(fputc fputs fwrite fprintf)
对文件进行读取时有以下函数(fgetc fgets fread fscanf)
对文件操作完成后,要关闭文件-fclose
- 通过文件指针变量能够找到与它关联的文件。
不同的C编译器的**FILE类型(文件流指针)**包含的内容不完全相同,但是大同小异。每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,使用者不必关心细节。一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。另外文件指针默认是指向文件开头,而要对文件部分进行操作时涉及到。
问:为什么不直接传参?
因为电脑文件太多,中央处理器每次传参不能全部接收,所以传地址是最好的解决办法。
函数示例
fopen():打开文件
FILE fopen(const char *path, const char *mode);
附:mode
注:"w"会截断原文件,文件流指针指向文件头部
fread():读取文件
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
ptr: 将读到的内容保存在ptr中
size: 读数据块的大小
nmemb: 块的个数
stream: 文件流指针,读取位置
返回值: 返回成功读到的个数
常用于: 将块的大小指定为1,块的个数就是ptr内存空间的大小
fwrite():写入文件
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
ptr: 将写入的数据保存在ptr中
size: 写入数据块的大小
返回值: 返回成功写入的个数
常用于: 将块的大小指定为1,块的个数就是ptr内存空间的大小
fseek():根据文件指针的位置和偏移量来定位文件指针
int fseek(FILE *stream,long int offset,int whence);
offset: 偏移量,针对第三个参数whence
whence: 定位文件流指针 SEEK_SET,SEEK_END,SEEK_CUR
#include<stdio.h>
int main()
{
FILE *pFile = fopen("example.txt", "wb"); //此时文件无内容
fputs("Thisisanapple.", pFile);
fseek(pFile, 8, SEEK_SET); //将文件指针指向第八个字符的地址
fputs("sam", pFile); //从第八个字符替换原字符串,Thisisansamle. ,允许越界读写
fclose(pFile);
return 0;
}
fclose():退出文件
int fclose(FLIE *fp);
#include <stdio.h>
int main() {
FILE* fp = fopen("tmp.txt", "w+");
if(!fp) {
perror("fp");
return 0;
}
const char* lp = "linux-66";
int ret = fwrite(lp, 1, 8, fp);
if(ret == 8)
printf("write size [%d]\n", ret);
fseek(fp, 0, SEEK_SET);
char arr[1024] = {0};
ret = fread(arr, 1, sizeof(arr) - 1, fp);
if(ret == 8)
printf("read size [%d]\n", ret);
fclose(fp);
return 0;
}
ftell():返回文件指针相对于起始位置的偏移量
long int ftell(FILE *stream);
#include<stdio.h>
int main()
{
FILE *pFile;
long size;
pFile = fopen("example.txt", "rb"); //文件中的字符串:Thisisanapple.sam
if (pFile == NULL)
perror("Erroropeningfile"); //若未打开文件,则输出错误信息
else
{
fseek(pFile, 0, SEEK_END);
size = ftell(pFile);
fclose(pFile);
printf("Sizeofmyfile.txt: %ld bytes.\n", size); //17个字节
return 0;
}
rewind():让文件指针的位置回到文件的起始位置
void rewind(FILE *stream);
#include<stdio.h>
int main()
{
int n;
FILE *pFile;
char buffer[27];
pFile = fopen("example.txt", "w+"); //此时文件无内容
for (n = 'A'; n <= 'Z'; n++)
fputc(n, pFile); //将大写字母表写入文件
rewind(pFile); //将文件指针指向文件头
fread(buffer, 1, 26, pFile); //读取文件中前26个字节
fclose(pFile);
buffer[26] = '\0';
puts(buffer);
return 0;
}
remove():删除文件
int remove(const char * filename);
#include<stdio.h>
int main()
{
char filename[100];
printf("The file to delete:");
gets(filename); //从控制台获取文件名,这里选择上面留下的'example.txt'
if (remove(filename) == 0)
printf("Removed %s.", filename);
else
perror("remove"); //若为删除,提示错误信息
return 0;
}
注:perror()函数提示的错误信息
· EROFS 欲写入的文件为只读文件。
· EFAULT 参数filename 指针超出可存取内存空间。
· ENAMETOOLONG 参数filename 太长。
· ENOMEM 核心内存不足。
· ELOOP 参数filename 有过多符号连接问题。
· EIO I/O 存取错误。
feof():判断文件执行情况
int feof(FILE *stream); 如果遇到文件结束,函数值为非零值,否则函数值为0。
注:此处的文件结束标志是EOF,EOF的16进制代码为0xFF(十进制为-1),特用在文本文件中,因为在文本文件中
数据是以ASCⅡ代码值的形式存放,普通字符的ASCⅡ代码的范围是32到127(十进制),与EOF不冲突,因此可以直接使用。
但是在二进制文件中,数据有可能出现-1,因此不能用EOF来作为二进制文件的结束标志,可以通过feof函数来判断。
牢记: 在文件读取过程中,不能用feof函数的返回值直接用来判断文件的是否结束。而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束。
- 文本文件读取是否结束,判断返回值是否为EOF (fgetc),或者NULL(fgets)
例如:fgetc判断是否为EOF.;fgets判断返回值是否为NULL. - 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
例如:fread判断返回值是否小于实际要读的个数。