不能天天看 plmm 的,偶尔也要换换口味的
我的木村拓哉啊
1 文件概述
1.1 文件的分类
文件通常是存储在外部介质上的,如磁盘。在使用时才读入内存。
从不同的角度可以对文件做不同的分类
1.1.1 从用户角度
(1) 普通文件
指存储在磁盘或其他介质上的一段已命名的存储区。对于我们而已,如 test,txt 就是一个文件的名称,该文件中包含着系列以二进制形式(0或1)存储的数据。
(2) 设备文件
指与主机相连的的各种外部设备,如显示器,打印机,键盘等。文件系统把外部设备也看成一个文件来进行管理,输入输出操作等同于对磁盘文件的读写操作。
1.1.2 从文件存取方式
(1) 顺序文件
从头到尾顺序存取的文件
(2) 随机文件
随机文件的记录通常具有固定长度,可以直接访问文件中的特定记录,也可以把数据插入到文件特定位置中
1.1.3 从文件编码方式
(1) ASCII 码文件(文本文件 txt)
在磁盘中存放时每个字符对应一个字节(8位),用记事本打开是可读的
例如,数5678的存储形式为:
ASC码: 00110101 00110110 00110111 00111000 (共占用4个字节)
↓ ↓ ↓ ↓
十进制码: 5 6 7 8
(2) 二进制码文件(bin等)
在磁盘中按二进制的编码方式来存放文件,不具有可读性。(如用记事本打开一个图片)
例如, 数5678的存储形式为: 00010110 00101110(只占二个字节)
1.2 流和文件指针
1.2.1 流
流是程序输入或输出的一个连续的数据序列,类似于水管里的水
1.2.2 文件指针
文件指针指向一个结构体类型,名为 FILE
FILE *文件指针
1.2.3 文件的操作流程
C 程序不能直接对磁盘文件进行操作,需要通过内存中的变量来实现。
基本步骤:
- 建立/打开文件
- 从文件中读取数据或向文件中写数据
- 关闭文件(取消程序与文件的联系)
2 文件操作
2.1 文件的打开和关闭
2.1.1 打开文件
// 成功打开可以观察到非 0 值,否则返回 NULL
fopen(文件名,文件使用模式)
根据指定的模式打开指定的文件,由一个文件指针指向它,通过文件指针来操作文件
2.1.2 关闭文件
fclose(文件指针)
该文件指针是已打开过的文件指针。执行本函数时,若文件关闭成功,返回 0,否则返回 -1
2.1.3 判断文件结束
// 文件结束:返回非0值,文件未结束,返回0值
feof(文件指针)
2.2 文件的字符输入输出函数
2.2.1 字符输入函数(读取)
ch = getc(文件指针) 或 ch = fgetc(文件指针)
这两个函数在使用上区别不大,不同在于内部实现
从文件中读出数据,保存到内存变量中。
例:
#include<stdio.h>
int main()
{
FILE *fp; /*声明文件指针和字符串*/
char ch;
if((fp=fopen("D:\\test.txt","r")) != NULL)/*以只读的方式打开文件*/
{
ch = getc(fp);
}
printf("%c\n",ch);/*打印字符串*/
fclose(fp);
return 0;
}
结果:
2.2.2 字符输出函数(写入)
将内存变量中的数据写到文件中
putc(ch,文件指针) 或者 fputc(ch,文件指针)
成功则把 ch 中的数据写入到文件中;否则返回文件结束标志 EOF(-1)
例:
#include<stdio.h>
int main()
{
FILE *filePointer = NULL;
filePointer = fopen("D:\\test.txt", "w+");
char ch = 'c';
putc(ch,filePointer);
return 0;
}
结果:
2.2.3 综合例子
#include<stdio.h>
int main()
{
FILE *fp1;
FILE *fp2;
char c_tmp;
if((fp1 = fopen("D:\\test_r.txt","r")) == NULL)
{
fclose(fp1);
printf("file is not exist");
return 0;
}
// 文件的打开写操作,会清除文件
fp2 = fopen("D:\\test_w.txt", "w+");
// 不能在指定初值的时候指定成EOF
c_tmp=0;
// 判断是否读到了文件结尾, 或者用 if(!feof(fp1))
// 文件结束:返回非0值,文件未结束,返回0值
while(c_tmp != EOF)
{
c_tmp=fgetc(fp1);
fputc(c_tmp,fp2);
printf("%c", c_tmp);
}
fclose(fp1);
fclose(fp2);
system("pause");
return 0;
}
运行结果
2.3 文件的字符串输入输出函数
2.3.1 字符串输入函数
fgets() ,每次从文件中读出 n-1 个字符并保存到内存变量中。如果在未读满 n-1 个字符之时,已读到一个换行符(\n)或一个EOF(文件结束标志),则结束本次读操作。读入的字符串中最后包含读到的换行符,因此,确切地说,调用fgets函数时,最多只能读入n-1个字符。读入结束后,系统将自动在最后加 '\0',并以 str 作为函数值返回。
// 从 stream 流中读取 n-1 个字符存储到字符指针变量 s 所指向的内存空间。
char *fgets(char *s, int n, FILE *stream);
执行成功返回文件中的字符串,否则返回 NULL(0) 或文件结束标记EOF(-1)
例:
#include <stdio.h>
int main()
{
FILE *filePointer = NULL;
char buff[255];
filePointer = fopen("D:\\test.txt", "r");
fgets(buff, 255, (FILE*)filePointer);
printf("%s\n", buff );
fclose(filePointer);
}
D:\\test.txt
结果:
2.3.2 字符串输出函数
将存放在内存变量中的字符串写到文件中
fputs(字符变量,文件指针)
成功时返回0,否则返回文件结束标识 EOF(-1)
例
#include <stdio.h>
int main() {
// 申明文件指针
FILE *filePointer = NULL;
// 以追加模式打开文件 test.txt
filePointer = fopen("D:\\test.txt", "a+");
// 在test.txt文件末尾追加写入
fputs("dog is good!", filePointer);
// 关闭文件
fclose(filePointer);
return 0;
}
结果:
注意: 只有用 r+ 模式打开文件才能插入内容,w 或 w+ 模式都会清空掉原来文件的内容再来写,a 或 a+ 模式即总会在文件最尾添加内容。
2.3.3 综合例子
#include<stdio.h>
int main()
{
FILE *fp1;
FILE *fp2;
char buff[255];
int i;
//文件读操作,在打开文件之前需要确认文件是存在的
fp1 = fopen("D:\\test_r.txt","r");
if(fp1 == NULL){
printf("file is not exist");
return 0;
}
//文件的打开写操作,会清除文件,
fp2 = fopen("D:\\test_w.txt", "w+");
for (i = 0; i < 2; i++)
{
// 未结束返回 0
if(!feof(fp1))
{
fgets(buff, 255, fp1);
printf("%s", buff );
fputs(buff, fp2);
}
}
fclose(fp1);
fclose(fp2);
system("pause");
return 0;
}
运行结果:
2.4 文件的格式化输入输出函数
2.4.1 格式化输入函数
从文本文件中按格式输入,成功时返回读取的字节数,读到文件末尾返回文件结束标志 EOF(-1),若没有字段被读取返回0
fscanf(filePointer,格式串,输入项表)
例
#include <stdio.h>
int main()
{
FILE *filePointer = NULL;
char buff[255];
filePointer = fopen("D:\\test.txt", "r");
// 在遇到第一个空格和换行符时,它会停止读取
fscanf(filePointer, "%s", buff);
printf("%s\n", buff );
fclose(filePointer);
}
D:\\test.txt
结果
2.4.2 格式化输出函数
按指定的格式将内存中的数据转换成对应的字符,再以 ASCII码形式输出到磁盘中的文本文件中。
成功返回所写的字节数,出错返回负数
fprintf(filePointer,格式串,输出项表)
例
#include <stdio.h>
int main() {
// 申明文件指针
FILE *filePointer = NULL;
// 以追加模式打开文件 test.txt
filePointer = fopen("D:\\test.txt", "w");
// 在test.txt文件末尾追加写入
fprintf(filePointer,"%s", "cat is cute");
// 关闭文件
fclose(filePointer);
return 0;
}
结果
2.5 文件的数据块输入输出函数
数据块输入输出函数只适用于二进制文件
2.5.1 数据块输入函数
fread(start,size,count,fp);
start:输入数据在内存中存放的起始地址
size:要读取的字节数,即每个数据块的字节数
count:每次读取数据块的个数
fp:文件指针成功时返回实际读取的数据块的个数,出错或遇到文件末尾时返回0
2.5.2 数据块输出函数
fwrite(start,size,count,fp)
2.5.3 伸出你们的双手一起创造 Bug
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fp;
char c[] = "Cat is cute!";
char buffer[20];
/* 打开文件用于读写 */
fp = fopen("D:/test.txt", "w+");
/* 写入数据到文件 */
fwrite(c, strlen(c) + 1, 1, fp);
/* 重置写指针到文件的开头 */
fseek(fp, 0, SEEK_SET);
/* 读取并显示数据 */
fread(buffer, strlen(c)+1, 1, fp);
printf("%s\n", buffer);
fclose(fp);
return(0);
}
控制台输出:
test.txt
3 文件定位操作
3.1 取文件位置指针的当前值
ftell(filePointer)
该函数返回的当前文件位置指针值是相对于文件开头的位移量
3.2 移动文件位置指针
fseek(filePointer,offset,from)
offset:文件位置指针的位移量
from:起始点,用来指定位移量是以哪个位置为基准的
3.3 置文件指针于文件开头
rewind(filePointer)
将文件位置指针重新指向文件的开头位置