文件操作详解(上)

简介: 文件操作详解

一、文件的简单介绍


1.1 什么是文件


从广义上来说,磁盘上的文件是文件。在C语言阶段我们在执行一段程序过后,它的内容随着进程的结束而消失,而我们要想把数据持久化,数据存放在磁盘文件、存放到数据库等方式。今天简单介绍数据保存到文件这种方式。在程序设计中,我们一般谈的文件有两种:程序文件和数据文件(从文件功能的角度来分析).


1.2 程序文件


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


1.3 数据文件


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


本章讨论的是数据文件。在以前各章所处理数据的输入输出都是以终端为对象的,即从终端的键盘输入数据,运行结果显示到显示器上。其实有时候我们会把信息输出到磁盘上,当需要的时候再从磁盘上把数据读取到内存中使用,这里处理的就是磁盘上文件。


1.4 文件名


一个文件要有一个唯一的文件标识,以便用户识别和引用。

文件名包含3部分:文件路径+文件名主干+文件后缀

例如:c:\code\test.txt为了方便起见,文件标识常被称为文件名。


二、文件的打开和关闭


2.1 文件指针


1、缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”。

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


例如,VS2013编译环境提供的 stdio.h 头文件中有以下的文件类型申明:

typedef struct _iobuf 
{
    char*  _ptr;
    int  _cnt;
    char*  _base;
    int  _flag;
    int  _flag;
    int  _file;
    int  _charbuf;
    int  _bufsiz;
    char*  _tmpfname;
}FILE;


每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量填充其中的信息,一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。


比如我们可以创建一个FILE*的指针变量:


FILE* pf;//文件指针变量


该类型的意义是:


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


2.2 文件的打开与关闭


文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。

在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。

ANSIC 规定使用fopen函数来打开文件,fclose来关闭文件。

//打开文件
FILE*  fopen(const char* filename,const char* mode);
//关闭文件
int fclose(FILE* stream);


我们这里可以简单介绍一下 fopen 和 fclose函数。


①fopen

FILE*  fopen(const char* filename,const char* mode);

打开一个文件以什么形式打开,mode就是打开的方式。如果打开成功就返回文件指针的起始地址,如果失败就返回NULL,而这也暗示我们要进行检查。


②fclose

int fclose(FILE* stream);


这个函数比较简单,就是关闭之前打开的文件。如果打开成功,就返回0,如果失败,就返回EOF.


上面对于mode(打开方式)介绍的比较含糊,那么具体的打开方式有如下这些方式:


1669216361259.jpg


常用的就是标红的那些,需要注意的是:


1.以"r"(只读的方式)来打开文件,需要打开一个原本已经存在的文本文件,否则会打开失败。


2.如果以"w"(只写的方式)来打开文件,无论文本文件是否存在,无论文本里面有没有内容,都会开辟一个文件,而且需要注意如果已经存在的文件,那么它会把文件里原本的内容清除,然后存入数据。如果不想清除原本文件内的数据,可以使用第三种方式


3."a"(追加的方式),向文本文件尾添加数据。


4.至于这些字母后面加个b,"wb","rb","ab"意思是以二进制的形式。上述是以文本的形式。


使用演示:

#include<stdio.h>
#include<errno.h>
#include<string.h>
int main()
{
  FILE* pf = fopen("test.txt", "r");//pf的类型是FILE*
  //文件打开可能失败,所以要判断
  if (pf == NULL)
  {
  printf("%s\n", strerror(errno));
  return 1;
  }
  //"r" "w" "a"  "r+"  "w+"  "a+"  "rb"  "wb" 
  //写文件
  //关闭文件
  fclose(pf);
  pf = NULL;
  return 0;
}

这里是和之前我讲述的动态开辟比较相似,那里需要对malloc或者calloc开辟的动态内存进行判断是否为NULL,然后在结束的时候需要free掉动态内存,和这里的文件操作是比较相似的。可以类比着记忆。


2.3 文件的流程展示


通过我简单的介绍,大家对于文件有了基本了解,而具体是如何操作的,那是下面要介绍的内容,而这里笔者简单画了个图帮助大家理解:


1669216386966.jpg


三、文件的顺序读写


1669216399643.jpg


3.1 fputc(写字符)


int fputc ( int character, FILE * stream );

1、Charcater: 要编写的字符的整型升级。写入时,该值在内部转换为无符号字符。


2、Stream:指向标识输出流的 FILE 对象的指针。该函数的意义就是将字符character写入文件中去。


3、如果成功后,将返回写入的字符。如果发生写入错误,则返回 EOF 。


应用展示:

1669216420659.jpg


3.2 fgetc(读字符)


int fgetc ( FILE * stream );

1、在默认状态下,fgetc从stream指向的文件首个字符开始读取,当读取过后,自动指向下一个字符,如果指向末尾或者读取失败则返回EOF。


2、如果成功,则返回当前指向的字符,如果失败,则返回EOF。


应用展示:


①一个一个读取


1669216441619.jpg


注意:这里之所以能读出a b c d是因为在上个函数fpuc时笔者写入了一个txt文件里面是a到c的字符,所有各位朋友在使用这个函数的时候记得不是空的文件,否则会出错。


②全部读取


如果仅能一个一个读取,那么效率有点低了,如果我们想全部读取文件里的内容,那么我们根据fgetc函数的返回值可以设计,当指向文件尾时返回EOF。


展示:


1669216450297.jpg


3.3 fputs(写字符串到文件)


int fputs ( const char * str, FILE * stream );

1、意义:将 str 所指向的字符串写入流(stream)。


2、该函数开始从指定的地址 (str) 复制,直到到达终止空字符 ('0')。此终止空字符不会复制到流中。


3、请注意,之前fputc和putc以及fgetc和getc是非常相似的,而这里fputs 不仅与 puts 不同,因为可以指定目标流,而且 fputs 不会写入其他字符,而 puts 会自动在末尾追加换行符。


4、如果成功,则返回一个非0的数,如果失败,则返回EOF。


应用展示:


1669216474607.jpg


这里我之前写入的"abcdef..."已经消失了,是因为笔者以"w"(只写)的方式打开了文本,会自动清除里面原本的内容,要想保留下来原本的内容,可以以"a"(追加)的方式打开。


3.4 fgets(读字符串)


char * fgets ( char * str, int num, FILE * stream );

1、意义:从流(stream)中读取(num-1)字符并将其作为字符串存储到 str 中。


2、当读取 (num-1) 字符或达到换行符或文件末尾(以先发生者为准)时停止,需要注意换行符(\n)使fgets停止读取,但它被视为有效字符,并包含在复制到str的字符串中。


3、终止空字符('\0')会自动追加到复制到 str 的字符之后。


4、请注意,fgets 与 gets 相同之处在于:fgets和gets都会自动追加终止空字符,不同:fgets 不仅接受流参数(stream),还允许指定读取字符个数,并且fgets遇到换行符会把换行符当作字符拷贝到str中。


5、如果成功,返回str,如果失败,则返回NULL指针.


应用展示:


1669216494079.jpg


这里要求打印5个字符只打印了4个字符的原因是,它自动追加'\0'算作一个字符。


接下来这两个函数是针对所有输出输入流的:


1669216502517.jpg

相关文章
|
5月前
|
移动开发 Linux 程序员
c++文件操作,超详细
c++文件操作,超详细
95 0
|
11月前
|
存储 C语言 Windows
文件操作(上)
文件操作(上)
50 0
|
4月前
|
存储 C++
C++文件操作
C++文件操作
|
5月前
|
存储 程序员 编译器
文件操作(1)
文件操作(1)
45 2
|
4月前
|
存储 程序员 编译器
文件操作详解
文件操作详解
54 0
|
5月前
|
C++
轻松学会文件操作(2)
轻松学会文件操作(2)
|
5月前
|
存储 程序员 编译器
|
5月前
|
存储 Java C语言
文件操作你会了吗
文件操作你会了吗
70 0
|
11月前
|
程序员 编译器 C语言
文件操作(中)
文件操作(中)
35 0
|
11月前
|
存储 C语言
文件操作介绍(下)
文件操作介绍(下)
56 0