C语言文件操作

简介: C语言文件操作

一、文件概述

1、文件:文件是计算机文件属于文件的一种,与普通文件载体不同,计算机文件是以计算机硬盘为载体存储在计算机上的信息集合。 文件可以是文本文档、图片、程序等等。

2、文件可以分为:数据文件和程序文件 。

3、文件名:唯一的文件标识,文件名包含三部分:文件路径、文件名、文件后缀。

注意:

  • 文件名可以不包含后缀名。
  • 文件中不能包含这些字符:\/:*?"<>|。
  • 文件路径指的是从盘符到该文件所经历的路径中各符号名的集合。
  • 文件后缀名决定了一个文件的默认打开方式。

二、文件的打开与关闭

1、文件指针

文件指针:文件类型指针,简称文件指针。

每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统声明的,取名FILE。

我们可以这样定义一个文件指针:

FILE* pf;

定义 pf 是一个指向 FILE 类型数据的指针变量。可以使 pf 指向某个文件的文件信息区(是一个结构体变量)。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够找到与它关联 的文件。

2、打开文件

fopen(const char*  filename,const char*  mode):文件打开函数。
  • filename:要打开的文件的文件名称,以字符串的形式。
  • mode:文件访问模式,以字符串的形式。

文件访问模式:

演示:

#include<stdio.h>
int main()
{
  FILE* pf;
  pf = fopen("test.txt", "w");
  if (pf == NULL)
  {
    perror("fopen");
  }
}

我们刚开始是没有这个文件的,但是我们以只写的方式打开文件 ,但是若filename的文件不存在,那么fopen函数会自动创建文件。

#include<stdio.h>
int main()
{
  FILE* pf;
  pf = fopen("test1.txt", "r");
  if (pf == NULL)
  {
    perror("fopen");
  }
}

同样是打开的文件不存在,但是如果以只读的方式打开的话,就会打开失败。

所以,当我们打开文件时,若以“读”的模式打开,文件必须存在;若以“写”的模式打开时,文件可以不存在,会自动创建。

3、关闭文件

fclose(const char*  stream):文件关闭函数。

  • stream:文件指针

演示:

#include<stdio.h>
int main()
{
  FILE* pf;
  pf = fopen("test.txt", "r");
  if (pf == NULL)
  {
    perror("fopen");
  }
  fclose(pf);
  pf = NULL;
  return 0;
}

注意:

  • 在对文件操作完成之后,必须对文件进行关闭。
  • 必须对文件指针置为NULL,防止成为野指针。

三、文件顺序读写函数

text.txt的文件内容:

1、fgetc

int fgetc(FILE* stream):字符输入函数,适合所有输入流。

int main()
{
  FILE* pf;
  pf = fopen("test.txt", "r");
  if (pf == NULL)
  {
    perror("fopen");
  }
  char c = fgetc(pf);
  printf("%c", c);
  fclose(pf);
  pf = NULL;
  return 0;
}

运行结果:  

注意:fgetc函数是获取单个字符的,而且每调用一次指针就会自动向后移一位。

2、fputc

int fputc(int character,FILE* stream):字符输出函数,适合所有输出流。

int main()
{
  FILE* pf;
  pf = fopen("test.txt", "a");
  if (pf == NULL)
  {
    perror("fopen");
  }
  char c = 'h';
   fputc(c,pf);
  fclose(pf);
  pf = NULL;
  return 0;
}


运行结果:

3、fgets

int fgets(char* str,int num,FILE* stream):文本行输入函数,适合所有输入流。

  • str:读取的字符数组的指针
  • num:复制到str的最大字符数
  • stream:输入流FILE对象的指针
int main()
{
  FILE* pf;
  pf = fopen("test.txt", "r");
  if (pf == NULL)
  {
    perror("fopen");
  }
  char str[100] = { 0 };
   fgets(str,3,pf);
  printf("%s", str);
  fgets(str, 4, pf);
  printf("%s", str);
  fclose(pf);
  pf = NULL;
  return 0;
}


运行结果:

注意:fets函数不会自动换行,只有在读取到'\n' 才会换行。

4、fputs

int  fputs(const char* str,FILE* stream):文本行输出函数,适合所有的输出流。

  • str:要写入的字符串指针。
  • stream: 输出流FILE对象的指针。
int main()
{
  FILE* pf;
  pf = fopen("test.txt", "a");
  if (pf == NULL)
  {
    perror("fopen");
  }
  char str1[20] = "igklmn";
   fputs(str1,pf);
   char str2[20] = "12345";
   fputs(str2, pf);
  fclose(pf);
  pf = NULL;
  return 0;
}

运行结果:

fputs函数也不会自动换行,需要自行在字符串中加上'\n'

int main()
{
  FILE* pf;
  pf = fopen("test.txt", "a");
  if (pf == NULL)
  {
    perror("fopen");
  }
  char str1[20] = "igklmn\n";
   fputs(str1,pf);
   char str2[20] = "12345\n";
   fputs(str2, pf);
  fclose(pf);
  pf = NULL;
  return 0;
}

运行结果:

5、fscanf

int fcanf(FILE* stream,cost char* format,……):格式化输入函数,适合于所有流。

注意:该函数是从stream所指的文件中以指定形式读取信息到format参数所指的位置。

test2.txt的文件内容:

int main()
{
  struct S s = {0};
  FILE* pf = fopen("test2.txt", "r");
  if (NULL == pf)
  {
    perror("fopen");
    return 1;
  }
  fscanf(pf, "%s %d %f", s.name, &(s.age), &(s.score));
  printf("%s %d %f\n", s.name, s.age, s.score);
 
  fclose(pf);
  pf = NULL;
  return 0;
}

运行结果:

6、fprintf

int fprintf(FILE* stream,cost char* format,……):格式化输出函数,适合于所有流。

注意:该函数是从stream所指的文件中以指定形式输出信息到format参数所指的位置。

int main()
{
  struct S s = { "强明",15,90};
  FILE* pf = fopen("test2.txt", "a");
  if (NULL == pf)
  {
    perror("fopen");
    return 1;
  }
  fprintf(pf, "\n%s %d %f", s.name, s.age, s.score);
  fclose(pf);
  pf = NULL;
  return 0;
}


运行结果:

7、fwrite

size_t fwrite(void* ptr,size_t size,size_t count,FILE* stream):二进制输出函数,适合于文件类型。

  • ptr:指向内存块的指针
  • size:每个元素的大小
  • count:读取元素的数目
  • sream:输入流FILE对象的指针
int main()
{
  struct S s = { "张康",23,77};
  FILE* pf = fopen("test3.txt", "wb");
  if (NULL == pf)
  {
    perror("fopen");
    return 1;
  }
  fwrite(&s, sizeof(struct S), 1, pf);
  fclose(pf);
  pf = NULL;
  return 0;
}

运行结果:

输出文件到文件上显示乱码,原因是我们在写入的时候是以二进制方式,但是打开显示时却不是。

8、fread

size_t fread(void* ptr,size_t size,size_t count,FILE* stream):二进制输入函数,适合于文件类型。

int main()
{
  struct S s = { 0};
  FILE* pf = fopen("test3.txt", "rb");
  if (NULL == pf)
  {
    perror("fopen");
    return 1;
  }
  fread(&s, sizeof(struct S), 1, pf);
  printf("%s %d %f\n", s.name, s.age, s.score);
 
  fclose(pf);
  pf = NULL;
  return 0;
}

运行结果:

四、辨析scanf、fscanf、sscanf

scanf:标准的输入流,从标准输入(键盘)读取格式化数据。

fscanf:从所有的输入流读取格式化数据。

sscanf:从字符串中读取格式化数据。

五、文件的随机读写

1、fseek

int feek(FILE* strem,long offset,int origin):文件指针偏移函数。

int main()
{
  FILE* pf = fopen("test3.txt", "w+");
  if (NULL == pf)
  {
    perror("fopen");
    return 1;
  }
  char str[20] = "jintianyey";
  fputs(str, pf);
  fseek(pf, 3, SEEK_SET);
  char ch = fgetc(pf);
  printf("%c", ch);
  fclose(pf);
  pf = NULL;
  return 0;
}

运行结果:

2、ftell

long int ftell ( FILE * stream ):返回指针相对于起始位置的偏移量。

int main()
{
  FILE* pf = fopen("test3.txt", "w+");
  if (NULL == pf)
  {
    perror("fopen");
    return 1;
  }
  char str[20] = "jintianyey";
  fputs(str, pf);
  fseek(pf, 3, SEEK_SET);
  char ch = fgetc(pf);
  printf("%c\n", ch);
  int d = ftell(pf);
  printf("%d", d);
  fclose(pf);
  pf = NULL;
  return 0;
}

运行结果:

我们利用了fseek函数设置从开始位置向后偏移三个位置,那么为甚么指针此时的偏移量会是4呢?

我们在fseek函数之后又使用了fputs函数,这个函数获取完单个字符之后,指针会自动向后偏移一个位置。

3、rewind

void rewind ( FILE * stream ):让文件指针的位置回到起始位置。

int main()
{
  FILE* pf = fopen("test3.txt", "w+");
  if (NULL == pf)
  {
    perror("fopen");
    return 1;
  }
  char str[20] = "jintianyey";
  fputs(str, pf);
  fseek(pf, 3, SEEK_SET);
  int d = ftell(pf);
  printf("%d\n", d);
  rewind(pf);
  d = ftell(pf);
  printf("%d", d);
  fclose(pf);
  pf = NULL;
  return 0;
}

运行结果:

六、文本文件和二进制文件

在文件操作中,有的是文本文件,有的是二进制文件,那么两者到底有什么区别呢?

文本文件:数据在内存时以二进制的形式,输出时不加转换就是二进制文件。

文本文件:数据在外存时以ASCII码输入,在存储前需要转换,以ASCII码进行存储的就是文本文件。

 

字符一律以ASCII形式存储,数值型数据既可以用ASCII形式存储,也可以使用二进制形式存储。

七、文件读取结束的判定

1、feof

int feof( FILE * stream ):判断文件是否正常结束

当设置了与流关联的文件结束标识符时,该函数返回一个非零值,否则返回零。

注意:在文件读取过程中,不能用feof函数的返回值直接用来判断文件的是否结束。而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束。

2、判断文本文件是否正常结束

文本文件读取是否结束,判断返回值是否为EOFfgetc),或者NULLfgets

 

int main()
{
  FILE* pf = fopen("test.txt", "r");
  if (NULL == pf)
  {
    perror("fopen");
    return 1;
  }
  char ch = 0;
  while ((ch = fgetc(pf)) != EOF)
  {
    printf("%c", ch);
  }
  if (ferror(pf))
  {
    printf("I/O errors");
  }
  else if (feof(pf))
  {
    printf("Ended successfully");
  }
  fclose(pf);
  pf = NULL;
  return 0;
}

运行结果:

3、判断二进制文件是否正常结束

二进制文件的读取结束判断,可以利用fread返回值是否小于实际要读的个数来进行判断。

int main()
{
  FILE* pf = fopen("test.txt", "r");
  if (NULL == pf)
  {
    perror("fopen");
    return 1;
  }
  char ch[10] = { 0 };
  while ((fread(ch,1,1,pf))==1)
  {
    printf("%s", ch);
  }
  if (ferror(pf))
  {
    printf("I/O errors");
  }
  else if (feof(pf))
  {
    printf("Ended successfully");
  }
  fclose(pf);
  pf = NULL;
  return 0;
}

运行结果:

八、文件缓冲区

ANSIC 标准采用  缓冲文件系统  处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“ 文件缓冲区  从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根据C 编译系统决定的。


目录
相关文章
|
24天前
|
存储 程序员 C语言
【C语言】文件操作函数详解
C语言提供了一组标准库函数来处理文件操作,这些函数定义在 `<stdio.h>` 头文件中。文件操作包括文件的打开、读写、关闭以及文件属性的查询等。以下是常用文件操作函数的详细讲解,包括函数原型、参数说明、返回值说明、示例代码和表格汇总。
43 9
|
26天前
|
存储 数据管理 C语言
C 语言中的文件操作:数据持久化的关键桥梁
C语言中的文件操作是实现数据持久化的重要手段,通过 fopen、fclose、fread、fwrite 等函数,可以实现对文件的创建、读写和关闭,构建程序与外部数据存储之间的桥梁。
|
28天前
|
算法 C语言
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
100 3
|
1月前
|
存储 C语言
【c语言】玩转文件操作
本文介绍了C语言中文件操作的基础知识,包括文件的打开和关闭、文件的顺序读写、文件的随机读写以及文件读取结束的判定。详细讲解了`fopen`、`fclose`、`fseek`、`ftell`、`rewind`等函数的使用方法,并通过示例代码展示了如何进行文件的读写操作。最后,还介绍了如何判断文件读取结束的原因,帮助读者更好地理解和应用文件操作技术。
49 2
|
2月前
|
存储 C语言
C语言文件操作(2)
【10月更文挑战第2天】
|
3月前
|
C语言
C语言——文件操作
本文介绍了文件的基本操作,包括文件的打开、关闭、读取和写入。使用`fopen`函数以不同模式(如“r”、“w”等)打开文件,并通过`fclose`关闭。文章详细解释了如何利用`fputc`、`fputs`及`fprintf`进行格式化写入,同时介绍了`fgetc`、`fgets`和`fscanf`用于文件内容的读取。此外,还涵盖了二进制文件的读写方法以及如何通过`fseek`、`ftell`和`rewind`实现文件的随机访问。
57 1
C语言——文件操作
|
2月前
|
程序员 编译器 C语言
C语言底层知识------文件操作
本文详细介绍了文件操作的基本概念,包括文件的分类(程序文件和数据文件,其中着重于数据文件的文本文件和二进制文件),流的概念及其在C程序中的应用,以及标准输入输出流stdin、stdout和stderr的作用。作者通过示例展示了如何使用fopen、fclose和常见的读写函数如fgetc、fputc和fgets进行文件操作。
35 2
|
2月前
|
存储 缓存 编译器
文件操作——C语言
文件操作——C语言
|
2月前
|
存储 C语言
简述C语言文件操作
简述C语言文件操作
12 0
|
2月前
|
存储 文件存储 C语言
深入C语言:文件操作实现局外影响程序
深入C语言:文件操作实现局外影响程序