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 编译系统决定的。


目录
相关文章
|
6天前
|
C语言
C语言——文件操作
本文介绍了文件的基本操作,包括文件的打开、关闭、读取和写入。使用`fopen`函数以不同模式(如“r”、“w”等)打开文件,并通过`fclose`关闭。文章详细解释了如何利用`fputc`、`fputs`及`fprintf`进行格式化写入,同时介绍了`fgetc`、`fgets`和`fscanf`用于文件内容的读取。此外,还涵盖了二进制文件的读写方法以及如何通过`fseek`、`ftell`和`rewind`实现文件的随机访问。
25 1
C语言——文件操作
|
18天前
|
存储 C语言
C语言程序设计核心详解 第十章:位运算和c语言文件操作详解_文件操作函数
本文详细介绍了C语言中的位运算和文件操作。位运算包括按位与、或、异或、取反、左移和右移等六种运算符及其复合赋值运算符,每种运算符的功能和应用场景都有具体说明。文件操作部分则涵盖了文件的概念、分类、文件类型指针、文件的打开与关闭、读写操作及当前读写位置的调整等内容,提供了丰富的示例帮助理解。通过对本文的学习,读者可以全面掌握C语言中的位运算和文件处理技术。
|
1月前
|
C语言
【C语言篇】文件操作(下篇)
因为有缓冲区的存在,C语⾔在操作⽂件的时候,需要做刷新缓冲区或者在⽂件操作结束的时候关闭⽂ 件。如果不做,可能导致读写⽂件的问题。
|
1月前
|
存储 API 数据处理
C语言中的文件操作
C语言中的文件操作
66 0
|
1月前
|
C语言 索引
【C语言】文件操作全解速览
【C语言】文件操作全解速览
30 0
|
1月前
|
存储 程序员 C语言
【C语言篇】文件操作(上篇)
在程序设计中,我们⼀般谈的⽂件有两种:程序⽂件、数据⽂件(从⽂件功能的⻆度来分类的)。
|
1月前
|
存储 编译器 程序员
【C语言】文件操作讲解
【C语言】文件操作讲解
|
3月前
|
C语言
C语言——文件操作
C语言——文件操作
47 2
C语言——文件操作
|
3月前
|
存储 程序员 编译器
文件操作(C语言)
文件操作(C语言)
|
3月前
|
存储 C语言 C++
【C语言基础】:文件操作详解(前篇:准备知识)
【C语言基础】:文件操作详解(前篇:准备知识)