C语言——文件操作

简介: C语言——文件操作

C语言中有时要用到文件,那么如何用C语言来操作文件呢?


1、流的概念


我们程序的数据需要输出到外部设备上,也需要从外部设备输入到我们的C语言程序上,为了方便操作,我们抽象出了流的概念(到这里虽然你不理解,其实我也不理解,只需要记住流这个专业名词就好)。


一般情况下,我们要输入数据要先打开流,输入结束后要关闭流,文件操作也要打开文件,操作结束后关闭文件。

那为什么我们平时输入数据时没有打开对应的流呢?

其实C程序在我们开始写程序时就已经提前打开3个流了

stdin-标准输入流,大多数环境下从键盘上输入数据,scanf就是在标准输入流中读取数据;

stdout-标准输出流,大多数环境下在屏幕上输出数据,printf就是在标准输出流中输出数据;

stderr-标准错误流,大多数环境下在屏幕上输出数据;

stdin,stdout和stderr这三个流的类型就是FILE*,通常称为文件指针

C语言操作文件就是通过文件指针来打开和关闭文件的,进行一系列的文件操作;


2、文件的打开和关闭


我们在打开文件时会返回一个FILE*的指针,需要用一个FILE*类型的变量接收它;

ANSIC 规定使⽤ fopen 函数来打开⽂件, fclose 来关闭⽂件;


//打开文件
FILE*pf=fopen("const char *filename","const char *mode");
//关闭文件
fclose(pf);
pf=NULL;


filename 指的是文件名字,mode指的是打开模式      

例如:

int main()
{
//打开文件
FILE*pf=fopen("data.txt","w");
if(pf==NULL)
{
perror("pf");
return -1;
}
//关闭文件
fclose(pf);
pf=NULL;
 
return 0;
}


3、关于文件操作的函数


1、顺序读写介绍


fgetc

fgetc是从文件中读入一个字符,用只读的方式打开,返回值是int类型;



fputc

fputc是向文件中写入一个字符,用只写的方式打开文件



fgets

fgets是从文件中读入一串字符,用只读的方式打开;



fgets有三个参数,第一个是char *的指针,第二个是读入的字符个数,第三个是文件指针;

举个例子,fgets就是在p1指向的文件中读入至多4个字符,放入arr中;


为什么是至多四个字符,fgets函数规定的是读入num-1个字符,如果文件中不足num-1个字符,那么就有多少读多少,如果文件中足够num-1个字符,就读入num-1个字符;


fputs

fputs是向文件中写入一串字符串



举例:

#include <stdio.h>
 
int main ()
{
   FILE * pFile;
   char sentence [256];
   fgets (sentence,256,stdin);
   pFile = fopen ("mylog.txt","a");
   fputs (sentence,pFile);
   fclose (pFile);
   return 0;
}


fscanf

fscanf是格式化输入函数

scanf是从键盘向程序中格式化输入数据;

fscanf是文件中向程序中格式化输入数据;



fprintf

fprintf是从程序中向文件中格式化输入数据



fread

fread是用二进制的方式从文件中读取数据;



fread有四个参数,从文件中读取count个,大小为size字节的数据放入ptr中;



fwrite

fwrite是用二进制的方式从程序中向文件写入数据;



fwrite有四个参数,从ptr中读取count个,大小为size字节的数据放入文件中;



2、随机读写介绍


fseek

根据⽂件指针的位置和偏移量来定位⽂件指针;





文件中有光标,SEEK_SET是光标起始位置;

SEEK_CUR是光标的当前位置;

SEEK_END是光标末尾位置;

fseek可以调整光标的位置;


举例:

/* fseek example */
#include <stdio.h>
int main()
{
  FILE* pFile;
  pFile = fopen("data.txt", "wb");
  fputs("This is an apple.", pFile);
  fseek(pFile, 9, SEEK_SET);
  fputs(" sam", pFile);
  fclose(pFile);
  return 0;
}



用fseek将光标位置移到 a 的前面,再次写入" sam";


ftell

ftell是返回文件指针,也就是光标的当前位置相对于起始位置的偏移量;

举例:

计算文件有多少个字符:


/* ftell example : getting size of a file */
#include <stdio.h>
int main ()
{
 FILE * pFile;
 long size;
 pFile = fopen ("myfile.txt","rb");
 if (pFile==NULL) 
 perror ("Error opening file");
 else
 {
 fseek (pFile, 0, SEEK_END); // non-portable
 size=ftell (pFile);
 fclose (pFile);
 printf ("Size of myfile.txt: %ld bytes.\n",size);
 }
 return 0;
}


rewind

rewind是使文件指针,也就是光标回到起始位置;

3、文件读取结束后的原因判定


feof和ferror

feof是判断文件是否遇到了/0而正常结束,

ferror是判断文件是否遇到了错误而非正常结束,


文件读取结束的标志

文本文件

文本文件的读取结束标志是判断返回值是否为EOF或者NULL,

例如:

fgtec返回EOF表示文件读取结束;

fgets返回NULL表示文件读取结束;

#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 1;
 }
 //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);
}


二进制文件

二进制文件的读取结束标志是判断返回值是否小于预期要读的个数;

例如:fread判断返回值是否小于预期读入的字符个数;

举例:

#include <stdio.h>
enum { SIZE = 5 };
int main(void)
{
 double a[SIZE] = {1.,2.,3.,4.,5.};
 FILE *fp = fopen("test.bin", "wb"); // 必须⽤⼆进制模式
 fwrite(a, sizeof *a, SIZE, fp); // 写 double 的数组
 fclose(fp);
double b[SIZE];
 fp = fopen("test.bin","rb");
 size_t ret_code = fread(b, sizeof *b, SIZE, fp); // 读 double 的数组
 if(ret_code == SIZE) {
 puts("Array read successfully, contents: ");
 for(int n = 0; n < SIZE; ++n) printf("%f ", b[n]);
 putchar('\n');
 } else { // error handling
 if (feof(fp))
 printf("Error reading test.bin: unexpected end of file\n");
 else if (ferror(fp)) {
 perror("Error reading test.bin");
 }
 }
 fclose(fp);
}


4、文件缓冲区

解释


ANSIC标准采用“缓冲文件系统”处理的数据文件的, 所谓缓冲文件系统是指系统自动地在内存中为

程序中每一个正在使用的文件开辟一块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓冲区,

装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据, 则从磁盘文件中读取数据输

入到内存缓冲区 (充满缓冲区), 然后再从缓冲区逐个地将数据送到程序数据区 (程序变量等)。

缓冲区的大小根据C编译系统决定。

缓冲区的概念,还是为了方便数据的传输,



举例


洗袜子,你今天换了一双袜子,放在盆里,一次洗一双袜子,需要水,洗衣粉还要忍受凉水的冰冷,每天换一双袜子,每天都要洗,是不是很麻烦,也用的水多,不如我们攒的袜子多了,把盆装满了,一次性洗,是不是更方便,收袜子的时候,也是一次收获很多双袜子,类似于文件缓冲区,加快了数据传输效率


一个有味道的例子!

相关文章
|
2天前
|
存储 程序员 编译器
文件操作(C语言)
文件操作(C语言)
|
14天前
|
存储 C语言 C++
【C语言基础】:文件操作详解(前篇:准备知识)
【C语言基础】:文件操作详解(前篇:准备知识)
|
14天前
|
C语言
【C语言基础】:文件操作详解(后篇)-2
【C语言基础】:文件操作详解(后篇)
|
14天前
|
存储 C语言
【C语言基础】:文件操作详解(后篇)-1
【C语言基础】:文件操作详解(后篇)
|
17天前
|
数据库 C语言
C语言进阶 文件操作知识(上)
C语言进阶 文件操作知识(上)
14 3
|
17天前
|
存储 C语言
C语言进阶 文件操作知识(下)
C语言进阶 文件操作知识(下)
17 2
|
25天前
|
存储 编译器 数据库
【再识C进阶5(上)】详细介绍C语言文件操作——文件是用于存储数据
【再识C进阶5(上)】详细介绍C语言文件操作——文件是用于存储数据
|
3天前
|
存储 C语言
【c语言】详解文件操作(二)
【c语言】详解文件操作(二)
12 0
|
3天前
|
存储 程序员 编译器
【c语言】详解文件操作(一)
【c语言】详解文件操作(一)
5 0
|
1月前
|
存储 C语言
C语言文件操作
C语言文件操作
30 2