首页 > 其他分享 >c语言:文件操作

c语言:文件操作

时间:2024-03-26 16:30:11浏览次数:19  
标签:文件 语言 输出 int 函数 pFile FILE 操作 指针

1. 为什么使⽤⽂件?

如果没有⽂件,我们写的程序的数据是存储在电脑的内存中,如果程序退出,内存回收,数据就丢失 了,等再次运⾏程序,是看不到上次程序的数据的,如果要将数据进⾏持久化的保存,我们可以使⽤ ⽂件。

2. 什么是⽂件?

磁盘(硬盘)上的⽂件是⽂件。

但是在程序设计中,我们⼀般谈的⽂件有两种:程序⽂件、数据⽂件(从⽂件功能的⻆度来分类 的)。

2.1 程序⽂件

程序⽂件包括源程序⽂件(后缀为.c),⽬标⽂件(windows环境后缀为.obj),可执⾏程序(windows 环境后缀为.exe)。

2.2 数据⽂件

⽂件的内容不⼀定是程序,⽽是程序运⾏时读写的数据,⽐如程序运⾏需要从中读取数据的⽂件,或 者输出内容的⽂件。

本篇文章讨论的是数据⽂件。

在以前各章所处理数据的输⼊输出都是以终端为对象的,即从终端的键盘输⼊数据,运⾏结果显⽰到 显⽰器上。

其实有时候我们会把信息输出到磁盘上,当需要的时候再从磁盘上把数据读取到内存中使⽤,这⾥处 理的就是磁盘上⽂件。

2.3 ⽂件名

⼀个⽂件要有⼀个唯⼀的⽂件标识,以便⽤⼾识别和引⽤。

⽂件名包含3部分:⽂件路径+⽂件名主⼲+⽂件后缀

例如: c:\code\test.txt

为了⽅便起⻅,⽂件标识常被称为⽂件名。

3. ⼆进制⽂件和⽂本⽂件?

根据数据的组织形式,数据⽂件被称为⽂本⽂件或者⼆进制⽂件。

数据在内存中以⼆进制的形式存储,如果不加转换的输出到外存的⽂件中,就是⼆进制⽂件。 如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的⽂件就是⽂ 本⽂件。

⼀个数据在⽂件中是怎么存储的呢? 字符⼀律以ASCII形式存储,数值型数据既可以⽤ASCII形式存储,也可以使⽤⼆进制形式存储。  如有整数10000,如果以ASCII码的形式输出到磁盘,则磁盘中占⽤5个字节(每个字符⼀个字节),⽽ ⼆进制形式输出,则在磁盘上只占4个字节。

4. ⽂件的打开和关闭

4.1 流和标准流

4.1.1 流

我们程序的数据需要输出到各种外部设备,也需要从外部设备获取数据,不同的外部设备的输⼊输出 操作各不相同,为了⽅便程序员对各种设备进⾏⽅便的操作,我们抽象出了流的概念,我们可以把流 想象成流淌着字符的河。

C程序针对⽂件、画⾯、键盘等的数据输⼊输出操作都是通过流操作的。

⼀般情况下,我们要想向流⾥写数据,或者从流中读取数据,都是要打开流,然后操作。

4.1.2 标准流

那为什么我们从键盘输⼊数据,向屏幕上输出数据,并没有打开流呢?

那是因为C语⾔程序在启动的时候,默认打开了3个流:

• stdin - 标准输⼊流,在⼤多数的环境中从键盘输⼊,scanf函数就是从标准输⼊流中读取数据。

• stdout - 标准输出流,⼤多数的环境中输出⾄显⽰器界⾯,printf函数就是将信息输出到标准输出 流中。

• stderr - 标准错误流,⼤多数环境中输出到显⽰器界⾯。

这是默认打开了这三个流,我们使⽤scanf、printf等函数就可以直接进⾏输⼊输出操作的。

stdin、stdout、stderr 三个流的类型是: FILE* ,通常称为⽂件指针。  C语⾔中,就是通过 FILE* 的⽂件指针来维护流的各种操作的。

4.2 ⽂件指针

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

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

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

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

不同的C编译器的FILE类型包含的内容不完全相同,但是⼤同⼩异。

不同的C编译器的FILE类型包含的内容不完全相同,但是⼤同⼩异。

每当打开⼀个⽂件的时候,系统会根据⽂件的情况⾃动创建⼀个FILE结构的变量,并填充其中的信 息,使⽤者不必关⼼细节。 ⼀般都是通过⼀个FILE的指针来维护这个FILE结构的变量,这样使⽤起来更加⽅便。

下⾯我们可以创建⼀个FILE*的指针变量:

FILE* p;

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

4.3 ⽂件的打开和关闭

⽂件在读写之前应该先打开⽂件,在使⽤结束之后应该关闭⽂件。 在编写程序的时候,在打开⽂件的同时,都会返回⼀个FILE*的指针变量指向该⽂件,也相当于建⽴了 指针和⽂件的关系。

ANSI C 规定使⽤ fopen 函数来打开⽂件, fclose 来关闭⽂件。

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

mode表⽰⽂件的打开模式,下⾯都是⽂件的打开模式:

⽂件使⽤⽅式含义如果指定⽂件不存在
“r”(只读)为了输⼊数据,打开⼀个已经存在的⽂本⽂件出错
“w”(只写)为了输出数据,打开⼀个⽂本⽂件建⽴⼀个新的⽂件
“a”(追加)向⽂本⽂件尾添加数据建⽴⼀个新的⽂件
“rb”(只读)为了输⼊数据,打开⼀个⼆进制⽂件出错
“wb”(只写)为了输出数据,打开⼀个⼆进制⽂件建⽴⼀个新的⽂件
“r+”(读写)为了读和写,打开⼀个⽂本⽂件出错
“w+”(读写)为了读和写,建议⼀个新的⽂件建⽴⼀个新的⽂件
“a+”(读写)打开⼀个⽂件,在⽂件尾进⾏读写建⽴⼀个新的⽂件
“rb+”(读写)为了读和写打开⼀个⼆进制⽂件出错
“wb+”(读 写)为了读和写,新建⼀个新的⼆进制⽂件建⽴⼀个新的⽂件
“ab”(追加)向⼀个⼆进制⽂件尾添加数据建⽴⼀个新的⽂件
“ab+”(读 写)打开⼀个⼆进制⽂件,在⽂件尾进⾏读和写建⽴⼀个新的⽂件

实例代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
	FILE* pf = fopen("text.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//写文件

	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

5. ⽂件的顺序读写

5.1 顺序读写函数介绍

函数名功能适⽤于
fgetc字符输⼊函数所有输⼊流
fputc字符输出函数所有输出流
fgets⽂本⾏输⼊函数所有输⼊流
fputs⽂本⾏输出函数所有输出流
fscanf格式化输⼊函数所有输⼊流
fprintf格式化输出函数所有输出流
fread⼆进制输⼊

⽂件

fwrite⼆进制输出⽂件

上⾯说的适⽤于所有输⼊流⼀般指适⽤于标准输⼊流和其他输⼊流(如⽂件输⼊流);所有输出流⼀ 般指适⽤于标准输出流和其他输出流(如⽂件输出流)。

5.1.1 fgetc

fgetc函数从流中读字符。

int fgetc ( FILE * stream );

 例如:

#include <stdio.h>
int main ()
{
  FILE * pFile;
  int c;
  int n = 0;
  pFile=fopen ("myfile.txt","r");
  if (pFile==NULL) perror ("Error opening file");
  else
  {
    do {
      c = fgetc (pFile);
      if (c == '$') n++;
    } while (c != EOF);
    fclose (pFile);
    printf ("The file contains %d dollar sign characters ($).\n",n);
  }
  return 0;
}

该程序逐字符读取一个名为myfile.txt的现有文件,并使用n变量来计算文件中包含的美元字符数($)。

5.1.2 fputc

fputc函数写字符到流中

int fputc ( int character, FILE * stream );

 例如:

 此程序会创建一个名为example.txt的文件,并将abcdefghijklmnopqrstuvwxyz写入其中。

5.1.3 fgets

fgets从流中读字符串

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

 参数

str指向复制读取字符串的字符数组的指针。

num要复制到str中的最大字符数(包括终止的null字符)。

stream指向标识输入流的FILE对象的指针。std不能用作从标准输入读取的参数。

返回值

成功后,函数返回str。如果在尝试读取字符时遇到文件的末尾,则指示符号集(feof)的末尾。若在读取任何字符之前发生这种情况,则返回的指针为空指针(并且存储的内容不变)。如果发生读取错误,则会设置错误指示器(ferror),并返回一个空指针(但str指向的内容可能已更改)。

例如

#include <stdio.h>

int main()
{
   FILE * pFile;
   char mystring [100];

   pFile = fopen ("myfile.txt" , "r");
   if (pFile == NULL) perror ("Error opening file");
   else {
     if ( fgets (mystring , 100 , pFile) != NULL )
       puts (mystring);
     fclose (pFile);
   }
   return 0;
}

 此示例读取myfile.tx的第一行或前99个字符(以先到者为准),并将它们打印在屏幕上。

5.1.4 fputs

fputs函数将字符串写入

int fputs(const char *str, FILE *stream);
  • str 是要写入的字符串。
  • stream 是要写入的文件流

fputs 函数会将字符串 str 中的字符逐个写入到文件流 stream 中,直到遇到字符串结束符 \0。如果成功写入,则返回非负值;如果发生错误,则返回 EOF

例如:

#include <stdio.h>
int main()
{
	FILE* pc = fopen("example.txt", "w");
	if (pc == NULL)
	{
		perror("fopen");
		return 1;
	}
	else
	{
		fputs("ma jun jin da chang", pc);
	}
	return 0;
}

 

6. ⽂件的随机读写

6.1 fseek

fseek 是 C 语言中的一个标准库函数,用于设置文件流的位置指针,从而在文件中定位到特定的位置。它的函数原型如下:

int fseek ( FILE * stream, long int offset, int origin );
  • stream 是要设置位置的文件流,通常是通过 fopen 打开的文件指针。
  • offset 是偏移量,表示相对于 origin 的位置偏移。它的类型为 long int,通常是以字节为单位的偏移量。
  • origin 是起始位置,可以是下列常量之一:
    • SEEK_SET:从文件起始位置开始计算偏移量。
    • SEEK_CUR:从当前位置开始计算偏移量。
    • SEEK_END:从文件末尾位置开始计算偏移量。

fseek 函数会将文件流 stream 的位置指针设置为由 offset 和 origin 指定的位置。如果成功设置位置指针,则返回 0;如果发生错误,则返回非零值。

通过 fseek 函数,可以在文件中进行随机访问,定位到特定位置读取或写入数据。

例如:


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

6.2 ftell

 ftell 是 C 语言中的一个标准库函数,用于获取文件流的当前位置指针相对于文件起始位置的偏移量(以字节为单位)。它的函数原型如下:

long int ftell(FILE *stream);
  • stream 是要获取位置指针的文件流,通常是通过 fopen 打开的文件指针。

ftell 函数返回当前位置指针相对于文件起始位置的偏移量。如果成功获取,则返回当前位置的偏移量;如果发生错误,则返回 -1L

通常情况下,ftell 结合 fseek 可以用来获取当前文件的大小,或者在文件操作中记录当前位置以便后续操作。

标签:文件,语言,输出,int,函数,pFile,FILE,操作,指针
From: https://blog.csdn.net/uvrdes56dd6/article/details/137043305

相关文章

  • [计算机效率] 文件搜索工具:Listary(附详细使用教程)
    3.5文件搜索工具:ListaryListary是一款实用的搜索工具,它能为我的电脑(资源管理器)增添许多智能命令,提高用户日常收藏和整理文件的效率。它具备多种实用功能,例如收藏文件夹、快速打开最近浏览的文件夹,以及快速显示/隐藏文件扩展名等。此外,Listary还是一个轻量级的软件,不会过多......
  • 自然语言处理下载nltk模块库
    nltk安装目录nltk安装1.官方下载2.离线下载2.1下载nltk资料包2.2解压下载的资料包重命名2.2.1将解压后的packages文件夹重命名为nltk_data2.2.2查看将重命名的文件夹放在那个位置2.2.3将上述nltk_data文件夹放在2.2.2打印的位置处3.验证是否下载成功1.官......
  • ROS(机器人操作系统)
    参考:https://blog.csdn.net/qq_51963216/article/details/125754175下图及文字来自(遵循CC4.0BY-SA版权协议):https://blog.csdn.net/qq_51963216/article/details/125754175MoveIt由ROS(机器人操作系统)中一系列移动操作的功能包组成,包含运动规划,操作控制,3D感知,运动学,碰......
  • IT部门都想要的跨网文件交换解决方案,了解一下!
    近年来全球网络安全威胁态势的加速严峻,使得企业对于网络安全有了前所未有的关注高度,企业的网络安全体系建设正从“以合规为导向”转变到“以风险为导向”,从原来的“保护安全边界”转换到“保护核心数据资产”的思路上来。为了保护企业的核心数据资产,绝大多数企业都在内部实施了内......
  • C语言数组
    概念一组相同类型元素的集合定义intarr【10】={1,2,3,4,5,6,7,8,9};//定义一个整型数组,最多放10个元素。数组的下标数组的每个元素都有一个下标,下标从0开始,且数组通过下标来访问。如下面程序intmain(){    intarr【10】={10,11,12,13,14,15,16,17,18,19};    printf......
  • MySQL单表操作学习DDL_DML_DQL语句
    1创建数据库----DDL语句CREATETABLE`student`(`id`int(11)NOTNULLAUTO_INCREMENTCOMMENT'学号',`createDate`datetimeDEFAULTNULLCOMMENT'创建时间',`userName`varchar(20)DEFAULTNULLCOMMENT'用户名',`pwd`varchar(36)DEFA......
  • 使用go语言, 如何 只需一步调用,创建支付宝代扣
    使用go语言,如何只需一步调用,创建支付宝代扣  目标原理快速使用gitclonehttps://github.com/284851828/alilite_go.gitgomodtidygorundemo.go"#alilite_go"packagemainimport( "log" "time" c"alilite/client"//Replacewith......
  • 使用PHP语言, 如何 只需一步调用,创建支付宝代扣
    使用php语言,如何只需一步调用,创建支付宝代扣  目标原理"#alilite_php"<?phprequire_once'GatewaySdk.php';$appId="999999";//AppID向客户经理申请$sdk=newGatewaySdk($appId);$payload=['timestamp'=>1711347......
  • 【数据结构】C语言单链表的实现
    有时我们不用顺序表,而使用链表,是因为顺序表存在一定的问题1、顺序表的中间/头部的插入、删除需要挪动数据2、扩容需要申请新空间,拷贝数据,释放旧空间,存在性能的消耗3、会有空间的浪费单链表:不带头单向循环链表双链表:带头双向循环链表单链表的具体实现:1、单链表的创建:2......
  • 文件内容查看
    1.新建文件夹2.显示在dir1文件夹中file1的内容3.用nl命令列出文件的全部内容,包括行号,但空白行不加行号4.用nl命令的参数b列出file1的内容5.使行号前面自动补上0,统一输出格式,行号前默认补06.行号前按设置位数补07.以分页方式查看文件名file1的内容8.分页查看inst......