天天看点

文件的操作1.什么是文件2.文件的类型3.文件指针4.文件的顺序读写5.文件的随机读写6.文件的结束

文件的操作

  • 1.什么是文件
    • 程序文件
    • 数据文件
  • 2.文件的类型
    • 二进制文件
    • 文本文件
  • 3.文件指针
  • 4.文件的顺序读写
    • 字符输入/输出函数
      • fputc
      • fgetc
    • 文本行输入/输出函数
      • fputs
      • fgets
    • 格式化输入/输出函数
      • fprintf
      • fscanf
    • 二进制输入/输出函数
      • swrite
      • fread
  • 5.文件的随机读写
  • 6.文件的结束

1.什么是文件

文件就是存储在我们电脑中的一些数据,我们一般说的文件分为两种:程序文件和数据文件

程序文件

包括源程序文件(.c文件),目标文件(windows环境后缀为.obj),可执行程序(windows环境后缀为.exe)

数据文件

文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行时需要从中读取数据的文件,或输入的文件

我们这里讨论的就是数据文件

2.文件的类型

数据文件有两种存储模式,分别问二进制文件和文本文件;

二进制文件

电脑中的数据都是以二进制的形式存储的,如果不转换为其他的形式输出到外存,那么就是二进制文件

文本文件

如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件。

3.文件指针

每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的信息,(如文件的名字,文件的状态和文件的位置等。这些信息是保存在一个结构体变量中的。该结构体类型是由系统申明的,取名FILE。我们打开一个文件的时候,系统会返回一个文件指针来操作这个结构体的变量。

我们打开文件时用fopen这个函数,fclose这个函数来关闭文件。就像我们要对一个瓶子里面的东西进行使用,我们的第一步就是打开瓶盖,使用完之后再盖上盖子

FILE * fopen ( const char * filename, const char * mode );
int fclose ( FILE * stream );
           
文件的操作1.什么是文件2.文件的类型3.文件指针4.文件的顺序读写5.文件的随机读写6.文件的结束

我们可以写一些代码来看看如何操作

#include <stdio.h>
int main(){
	FILE* pf;
	pf=fopen("test.txt","w");//第一个参数是文件的路径,以写的方式打开,如果文件不存在就会创建一个新的文本文件
	if(pf!=NULL){//如果文件打开失败,会返回NULL,如果不为空,才能对文件进行操作
		//文件操作
		fclose(pf);//文件使用结束要关闭文件。
	}
	return 0;
}
           

4.文件的顺序读写

字符输入/输出函数

int fgetc ( FILE * stream );//字符输入函数,从文件中读取字符到程序中
int fputc ( int character, FILE * stream );//字符输出函数,往文件中写入字符
           

这两个函数只能在文件里进行存取单个字符的操作

例如:

fputc

#include <stdio.h>
int main(){
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL) {//如果打开文件失败,fopen会返回一个空指针,直接显示错误然后退出程序
		perror("fopen:");
		return 1;
	}
	int i = 0;
	for (i = 0; i < 26; i++) {//把26个字母写进文本文件中,写完一个pf会自动挪到下一个位置进行写入,不会覆盖。
		fputc('a' + i, pf);
	}
	fclose(pf);
	pf=NULL;
	return 0;
}
           

fgetc

#include <stdio.h>
int main(){
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL) {//如果打开文件失败,fopen会返回一个空指针,直接显示错误然后退出程序
		perror("fopen:");
		return 1;
	}
	int ch = 0;
	while ((ch=fgetc(pf))!=EOF)//fgetc函数读到一个字符之后指针就会指向下一位。如果读到了文件的末尾,fgetc会返回EOF
	{
		printf("%c ", ch);
	}
	fclose(pf);//一定要记得关闭文件指针
	pf=NULL;
	return 0;
}
           

文本行输入/输出函数

fputs

int fputs ( const char * str, FILE * stream );
int main() {
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL) {//如果打开文件失败,fopen会返回一个空指针,直接显示错误然后退出程序
		perror("fopen:");
		return 1;
	}
	fputs("hello\n", pf);
	fputs("world\n", pf);
	fclose(pf);//一定要记得关闭文件指针
	pf = NULL;
	return 0;
}
           

fgets

char * fgets ( char * str, int num, FILE * stream );
int main() {
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL) {//如果打开文件失败,fopen会返回一个空指针,直接显示错误然后退出程序
		perror("fopen:");
		return 1;
	}
	char arr[100];
	fgets(arr, 3, pf);//第一个参数是数组名,用来接收字符串,第二个参数是int类型,会读取n-1个字符
	//如果再调用,第一行没读完继续,如果读完了就会跳到第二行,
	fgets(arr, 2, pf);
	printf("%s", arr);
	fclose(pf);//一定要记得关闭文件指针
	pf = NULL;
	return 0;
}
           

格式化输入/输出函数

fprintf

int fprintf ( FILE * stream, const char * format, … );
struct S {
	char name[20];
	int age;
	double score;
};

int main() {
	struct S s = { "zhangsan",20,90.2 };
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL) {//如果打开文件失败,fopen会返回一个空指针,直接显示错误然后退出程序
		perror("fopen:");
		return 1;
	}
	fprintf(pf, "%s %d %f", s.name, s.age, s.score);//这个函数跟printf函数非常相似,
	//只是第一个参数增加了一个文件指针,把结构体的数据写到了文件里

	fclose(pf);//一定要记得关闭文件指针
	pf = NULL;
	return 0;
}
           
文件的操作1.什么是文件2.文件的类型3.文件指针4.文件的顺序读写5.文件的随机读写6.文件的结束

fscanf

int fscanf ( FILE * stream, const char * format, … );
struct S {
	char name[20];
	int age;
	double score;
};
int main() {
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL) {//如果打开文件失败,fopen会返回一个空指针,直接显示错误然后退出程序
		perror("fopen:");
		return 1;
	}
	struct S s = { 0 };
	fscanf(pf, "%s %d %lf", s.name, &(s.age), &(s.score));//这个函数和scanf很像,把文件中的数据格式化的读出来
	printf("%s %d %f", s.name, s.age, s.score);
	fclose(pf);//一定要记得关闭文件指针
	pf = NULL;
	return 0;
}
           
文件的操作1.什么是文件2.文件的类型3.文件指针4.文件的顺序读写5.文件的随机读写6.文件的结束

二进制输入/输出函数

swrite

size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
int main() {
	struct S s = { "zhangsan",20,90.2 };
	FILE* pf = fopen("test.txt", "wb");
	if (pf == NULL) {//如果打开文件失败,fopen会返回一个空指针,直接显示错误然后退出程序
		perror("fopen:");
		return 1;
	}
	fwrite(&s, sizeof(struct S), 1, pf);//第一个参数就是一个元素地址,第二个参数传入每个元素的大小,第三个参数传入元素个数
	fclose(pf);//一定要记得关闭文件指针
	pf = NULL;
	return 0;
}
           
文件的操作1.什么是文件2.文件的类型3.文件指针4.文件的顺序读写5.文件的随机读写6.文件的结束

fread

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
int main() {
	FILE* pf = fopen("test.txt", "rb");
	if (pf == NULL) {//如果打开文件失败,fopen会返回一个空指针,直接显示错误然后退出程序
		perror("fopen:");
		return 1;
	}
	struct S s = { 0 };
	fread(&s, sizeof(struct S), 1, pf);
	printf("%s %d %f", s.name, s.age, s.score);
	fclose(pf);//一定要记得关闭文件指针
	pf = NULL;
	return 0;
}
           
文件的操作1.什么是文件2.文件的类型3.文件指针4.文件的顺序读写5.文件的随机读写6.文件的结束

5.文件的随机读写

int fseek ( FILE * stream, long int offset, int origin );

这个函数可以调整读取字符指针的位置。第三个参数有三个取值,决定了偏移的方式,详情仔细看代码

SEEK_SET	//从文件的开始往右偏移offset个字符读取
SEEK_CUR	//从文件的中间往右偏移offset个字符读取
SEEK_END	//从文件的末尾往左偏移offset个字符读取
           

这么说可能比较抽象,我用代码给大家解释一下,文件中存储了这些子符

文件的操作1.什么是文件2.文件的类型3.文件指针4.文件的顺序读写5.文件的随机读写6.文件的结束
int main() {
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL) {
		perror("fopen():");
		return 1;
	}
	fseek(pf, 2, SEEK_SET);//从文件的开头往右偏移2个字符读取放到pf文件指针,就会读取到c
	int ch = fgetc(pf);
	printf("%c", ch);
	fclose(pf);
	pf = NULL;
	return 0;
}
           
文件的操作1.什么是文件2.文件的类型3.文件指针4.文件的顺序读写5.文件的随机读写6.文件的结束
int main() {
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL) {
		perror("fopen():");
		return 1;
	}
	int ch = fgetc(pf);
	fseek(pf, 2, SEEK_CUR);//从文件的中间开始读,上一个fgetc已经读取一个字符,文件指针会向右偏移一个,那么再偏移两个字符就是d
	ch = fgetc(pf);
	printf("%c", ch);
	fclose(pf);
	pf = NULL;
	return 0;
}
           
文件的操作1.什么是文件2.文件的类型3.文件指针4.文件的顺序读写5.文件的随机读写6.文件的结束
int main() {
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL) {
		perror("fopen():");
		return 1;
	}
	fseek(pf, -3, SEEK_END);//从文件的末尾往左偏移两个字符,第二个参数是负数.
	int ch = fgetc(pf);
	printf("%c", ch);
	fclose(pf);
	pf = NULL;
	return 0;
}
           
文件的操作1.什么是文件2.文件的类型3.文件指针4.文件的顺序读写5.文件的随机读写6.文件的结束

6.文件的结束

int feof ( FILE * stream );

这个函数很多人容易用错,这个函数不是判定文件是否结束,而是判断是否是正常的读取到了文件的末尾,还是中途出现错误而结束,如果正常读到了文件末尾结束返回非0值。其他错误返回0。

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    int c; // 注意:int,非char,要求处理EOF
    FILE* fp = fopen("test.txt", "r");
    if(!fp) {
        perror("File opening failed");
        return EXIT_FAILURE;
   }
 //fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF
    while ((c = fgetc(fp)) != EOF) // 标准C I/O读取文件循环
   { 
       putchar(c);
   }
 //判断是什么原因结束的
    if (ferror(fp))
        puts("I/O error when reading");
    else if (feof(fp))
        puts("End of file reached successfully");
    fclose(fp);
}
           

这就是C语言中比较容易用到的一些操作,如果有错误的地方欢迎在评论区留言,一起进步,谢谢。

继续阅读