死磕 C 语言文件

不能天天看 plmm 的,偶尔也要换换口味的

我的木村拓哉啊

1 文件概述

1.1 文件的分类

文件通常是存储在外部介质上的,如磁盘。在使用时才读入内存。

从不同的角度可以对文件做不同的分类

1.1.1 从用户角度

(1) 普通文件

指存储在磁盘或其他介质上的一段已命名的存储区。对于我们而已,如 test,txt 就是一个文件的名称,该文件中包含着系列以二进制形式(0或1)存储的数据。

(2) 设备文件

指与主机相连的的各种外部设备,如显示器,打印机,键盘等。文件系统把外部设备也看成一个文件来进行管理,输入输出操作等同于对磁盘文件的读写操作。

1.1.2 从文件存取方式

(1) 顺序文件

从头到尾顺序存取的文件

(2) 随机文件

随机文件的记录通常具有固定长度,可以直接访问文件中的特定记录,也可以把数据插入到文件特定位置中

1.1.3 从文件编码方式

参考:二进制文件和ASCII文件有何区别

(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 程序不能直接对磁盘文件进行操作,需要通过内存中的变量来实现。

基本步骤:

  1. 建立/打开文件
  2. 从文件中读取数据或向文件中写数据
  3. 关闭文件(取消程序与文件的联系)

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)

将文件位置指针重新指向文件的开头位置

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值