❤️C语言文件的操作与处理❤️----1.6W字详解,带你搞懂文件操作!!!(下)

简介: 想要通讯录的数据能保存,就涉及数据持久化的问题。我们一般数据持久化的方法有,把数据存放在磁盘文件、存放到数据库等方式。使用文件我们可以将数据直接存放在电脑的硬盘上,做到了数据的持久化。

⭐️⭐️ fread


size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );

image.png🔷举个栗子:

struct S
{
  int n;
  double d;
  char name[10];
};
int main()
{
  struct S s = { 0};
  FILE* pf = fopen("F:\\test.txt", "wb");    //打开文件
  if (pf == NULL)
  {
    perror("fopen");//打印错误信息
  }
  fread(&s, sizeof(struct S), 1, pf);
  printf("%d %lf %s\n", s.n, s.d, s.name);
  fclose(pf);
  pf = NULL;
  return 0;
}


⭐️⭐️ fwrite


size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );

image.png


🔷举个栗子:

struct S
{
  int n;
  double d;
  char name[10];
};
int main()
{
  struct S s = { 100,3.14,"zhuzhu"};
  FILE* pf = fopen("F:\\test.txt", "wb");    //打开文件
  if (pf == NULL)
  {
    perror("fopen");//打印错误信息
  }
  fwrite(&s, sizeof(s), 1, pf);
  fclose(pf);
  pf = NULL;
  return 0;
}

🔷在文件中储存的是二进制信息,显示出来是乱码的,虽然我们读不懂,但是计算机能够读懂它。

2b03941c84a84827adb69c31df8e5139.png

🔵🔵🔵那么到目前为止我们就学了三组相似类型的printf和scanf,来总结一下:image.png


⭐️⭐️ fseek


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

image.png

注:参数origin

image.png

🔷举个栗子:

/* fseek example */
#include <stdio.h>
int main ()
{
  FILE * pFile;
  pFile = fopen ( "example.txt" , "wb" );`在这里插入代码片`
  fputs ( "This is an apple." , pFile );
  fseek ( pFile , 9 , SEEK_SET );
  fputs ( " sam" , pFile );
  fclose ( pFile );
  return 0;
}

结果:

This is a sample. //当这段代码运行成功之后,example.txt文本里就会包含这句话


⭐️⭐️ ftell


long int ftell ( FILE * stream );

image.png

🔷举个栗子:

/* 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;
}

结果:此代码以字节为单位打印myfile.txt的大小,因为SEEK_END使指针指向文件末尾。


⭐️⭐️ rewind


void rewind ( FILE * stream );

image.png

🔷举个栗子:

从键盘输入一行字符,追加写入到一个文件中,再把该文件内容读出显示在屏幕上。

#include<stdio.h>
int main()
{
    FILE  *fp;
    char  ch;
    if((fp=fopen("C:\\Users\\dell\\Desktop\\abc.txt","ab+"))==NULL)
    {
        printf("\nCannot open file\nstrike any key exit\n");
        getchar();
        return 1;
    }
    printf("input a string:\n");
    ch=getchar();
    while(ch!='\n')
    {
        fputc(ch,fp);
        ch=getchar();
    }
    rewind(fp);        
    ch=fgetc(fp);          
    while(ch!=EOF)
    {
        putchar(ch);
        ch=fgetc(fp);
    }
    fclose(fp);
    return 0;
}

rewind(fp);每输入一个字符,文件内部位置指针向后移动一个字节。写入完毕,该指针已指向文件末尾, 如果要把文件从头读出,须把指针移到文件头,利用rewind()函数。


🔷三、文件结束判断与缓冲



1. 文件读取结束判断


⭐️⭐️ feof

int feof ( FILE * stream );
名称 详情
头文件 stdio.h
返回值 文件结束,则返回非0值,否则返回0
参数stream 目标文件指针
作用 当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束。


🔷被错误使用的feof


应当记住:在文件读取过程中,不能用feof函数的返回值直接用来判断文件的是否结束。

而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束。


文本文件读取是否结束,应该判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )

例如:

fgetc 判断是否为 EOF

fgets 判断返回值是否为 NULL

二进制文件的读取结束判断,是通过判断返回值是否小于实际要读的个数。

例如:

fread判断返回值是否小于实际要读的个数。

🔷举个栗子(文本文件的例子):

#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))//如果ferror返回非01值,说明文件读取发生错误
        puts("I/O error when reading");
    else if (feof(fp))//如果feof返回非0说明有读到文件末尾
        puts("End of file reached successfully");
    fclose(fp);
}

🔷举个栗子(二进制文件的例子):

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

🔷总结:


feof的用途:是当文件读取结束之后,判断是不是遇到文件末尾而结束的。

ferror的用途:是当文件读取结束之后,判断是不是遇到错误后读取结束的。

2. 文件缓冲区

ANSIC 标准采用“缓冲文件系统”处理的数据文件的。


所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”。


从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。


如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。


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


⭐️⭐️ fflush

int fflush(FILE *stream);

image.png

0961e732c3cf4c1eb6ad4f20f7e6192f.png

🔷举个栗子:

#include <windows.h>
//VS2013 WIN10环境测试
int main()
{
 FILE*pf = fopen("test.txt", "w");
 fputs("abcdef", pf);//先将代码放在输出缓冲区
 printf("睡眠10秒-已经写数据了,打开test.txt文件,发现文件没有内容\n");
 Sleep(10000);//这里是1000毫秒,就是10秒
 printf("刷新缓冲区\n");
 fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到文件(磁盘)
 //注:fflush 在高版本的VS上不能使用了
 printf("再睡眠10秒-此时,再次打开test.txt文件,文件有内容了\n");
 Sleep(10000);
 fclose(pf);
 //注:fclose在关闭文件的时候,也会刷新缓冲区
 pf = NULL;
 return 0; }

结论:

因为有缓冲区的存在,C语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。

如果不做,可能导致读写文件的问题。


相关文章
|
18天前
|
存储 C语言
【c语言】玩转文件操作
本文介绍了C语言中文件操作的基础知识,包括文件的打开和关闭、文件的顺序读写、文件的随机读写以及文件读取结束的判定。详细讲解了`fopen`、`fclose`、`fseek`、`ftell`、`rewind`等函数的使用方法,并通过示例代码展示了如何进行文件的读写操作。最后,还介绍了如何判断文件读取结束的原因,帮助读者更好地理解和应用文件操作技术。
26 2
|
23天前
|
存储 编译器 C语言
如何在 C 语言中判断文件缓冲区是否需要刷新?
在C语言中,可以通过检查文件流的内部状态或使用`fflush`函数尝试刷新缓冲区来判断文件缓冲区是否需要刷新。通常,当缓冲区满、遇到换行符或显式调用`fflush`时,缓冲区会自动刷新。
|
23天前
|
存储 编译器 C语言
C语言:文件缓冲区刷新方式有几种
C语言中文件缓冲区的刷新方式主要包括三种:自动刷新(如遇到换行符或缓冲区满)、显式调用 fflush() 函数强制刷新、以及关闭文件时自动刷新。这些方法确保数据及时写入文件。
|
1月前
|
存储 C语言
C语言文件操作(2)
【10月更文挑战第2天】
|
1月前
|
程序员 编译器 C语言
C语言底层知识------文件操作
本文详细介绍了文件操作的基本概念,包括文件的分类(程序文件和数据文件,其中着重于数据文件的文本文件和二进制文件),流的概念及其在C程序中的应用,以及标准输入输出流stdin、stdout和stderr的作用。作者通过示例展示了如何使用fopen、fclose和常见的读写函数如fgetc、fputc和fgets进行文件操作。
19 2
|
1月前
|
存储 缓存 编译器
文件操作——C语言
文件操作——C语言
|
1月前
|
C语言
【C语言】探索文件读写函数的全貌(三)
【C语言】探索文件读写函数的全貌
|
1月前
|
存储 C语言
【C语言】探索文件读写函数的全貌(二)
【C语言】探索文件读写函数的全貌
|
29天前
|
存储 C语言
简述C语言文件操作
简述C语言文件操作
9 0
|
1月前
|
存储 文件存储 C语言
深入C语言:文件操作实现局外影响程序
深入C语言:文件操作实现局外影响程序