编程技术是改变世界的力量。
本站
当前位置:网站首页 > 后端语言 > 正文

C语言之文件操作(c语言文件操作r+w+a+区别)

gowuye 2024-04-25 04:44 11 浏览 0 评论

文件基础概念

文件基础概念| 什么是文件

C语言中的文件是指一种数据存储形式,它通常用于在磁盘上保存数据。文件可以是文本文件、二进制文件和特殊文件,如设备文件等。

文件基础概念| 什么流

操作系统是以文件为单位对数据进行管理的,输入输出是数据传送的过程,数据如流水一样从一处流向另一处,因此常将输入输出形象地称为流(stream),即输入输出流。C语言把文件看作是一个字节的序列,即由一个一个字节的数据顺序组成。一个输入输出流就是一个字节流或二进制流。

文件基础概念| 文件标识

文件标识包括三部分:

  • 文件路径: 表示文件在外部存储设备中的位置。 表示文件在外部存储设备中的位置,通常文件路径可以用相对路径和绝对路径描述。绝对路径:可以直接通过路径找到存储位置。相对路径:相对于某个文件去描述路径。./ : 相对于某个文件的当前路径。../ : 相对于某个文件的上层路径。
  • 文件名主干:一般是文件名。
  • 文件后缀:表示文件的性质。如:.txt .doc .dat .c .h 。

文件基础概念| 文件分类

C语言中的文件可以分为以下几类:

  • 文本文件:以ASCII或Unicode字符编码的文件,可以用文本编辑器打开和编辑。
  • 二进制文件:包含二进制数据的文件,无法用文本编辑器直接读取或编辑。
  • 特殊文件:如设备文件、管道等,通常用于与操作系统进行通信或进行进程间通信。

文件基础概念| 文件缓冲区

文件缓冲区是用于暂存文件读写数据的内存空间,即在内存中开辟一段预留的空间,将文件数据先读入该空间中,并在需要时再从该空间中读取或往该空间中写入数据,以减少对磁盘的频繁读写次数。如上文提到的互联网知识所述,使用文件缓冲区可以缓和CPU与I/O设备之间速度不匹配的矛盾。

C语言文件操作

文件操作| 文件指针

在C语言中用一个指针变量指向一个文件,这个指针称为文件指针。通过文件指针就可对它所指的文件进行各种操作。C语言内置的文件指针类型FILE*,创建文件基本语法:FILE* pf;

在标准输入输出库库中,系统定义了三个FILE型的指针常量:

  • stdin(标准输入文件指针) 指向在内存中与键盘相应的文件信息区,因此,用它进行输入就蕴含了从键盘输入。
  • stdout(标准输出文件指针) 指向在内存中与显示器屏幕相应的文件信息区,因此,用它进行输出就蕴含了输出到显示器屏幕。
  • stderr (标准错误文件指针) 用来输出出错的信息,它也指向在内存中与显示器屏幕相应的文件信息区,因此,在程序运行时的出错的信息就输出到显示器屏幕。

文件操作| 文件位置

一般情况下,在对字符文件进行读写时,文件的位置指针指向文件开头,这时如果对文件进行读的操作,就读第一个字符,然后文件的位置指针顺序向后移一个位置,在下一次执行读的操作时,就将指针指向的第二个字符读入。 依此类推,直到遇文件尾。有时希望在一个文件的原有数据之后再添加新的数据,应该把文件位置指针移到文件尾,然后再接着写入新的数据,这就是文件的追加。注意:这个文件内部的位置指针与C语言中的指针不是一回事。位置指针仅仅是一个标志,表示文件读写到的位置,也就是读写到第几个字节,它不表示地址。文件每读写一次,位置指针就会移动一次,它不需要你在程序中定义和赋值,而是由系统自动设置,对用户是隐藏的。

C语言文件末尾通常是用EOF标识,通常可以通过int feof(FILE* _Stream);判定未见指针是否到达文件末尾,详细使用参见文件读写。

文件操作| 打开与关闭文件

在C语言中,可以使用标准I/O库提供的函数来打开和关闭文件。下面是打开和关闭文件的函数:

FILE* fopen(char const* _FileName,char const* _Mode):用于打开指定的文件,并返回一个文件指针。

  • _FileName:文件路径
  • _Mode:读写方式返回值:打开失败返回空指针

int fclose(FILE* _Stream):用于关闭指定的文件,并释放相关资源。

  • _Stream:关闭文件指针
  • 返回值:关闭成功返回0,失败返回EOF

打开方式详解

模式

含义

说明

r

只读

文件必须存在,否则打开失败

w

只写

若文件存在,则清除原文件内容后写入;否则,创建文件后写入

a

追加只写

若文件存在,则位置指针移到文件末尾,在文件尾部追加写入,故该方式不删除原文件数据;若文件不存在,则创建

r+

读写

文件必须存在。在只读 r 的基础上加 ‘+’ 表示增加可写的功能。

w+

读写

在只写 w 的基础上加 ‘+’ 表示增加可读的功能

a+

读写

在”a”模式的基础上,增加可读功能

rb

二进制读

功能同模式”r”,区别:b表示以二进制模式打开。下同

wb

二进制写

功能同模式“w”。二进制模式

ab

二进制追加

功能同模式”a”。二进制模式

rb+

二进制读写

功能同模式”r+”。二进制模式

wb+

二进制读写

功能同模式”w+”。二进制模式

ab+

二进制读写

功能同模式”a+”。二进制模式

文件打开常见失败原因

在文件操作总经常会出现文件打开失败问题,总结主要有以下几点原因。

  • 用”r”只读的方式打开一个不存在的文件
  • 文件路径错误
  • 文件名非法:反斜杠(\) 正斜杠 (/) 冒号 (:) 星号 (*) 问号 (?) 双引号 (“) 小于号 (<) 大于号 (>) 竖线(|)
  • 权限不够:以管理员身份运行该程序即可,例如C盘系统文件夹中文件打开

文件打开和关闭综合代码

#include <stdio.h>
int main()
{
  FILE* read = fopen("read.txt", "r");
  if (read == NULL)
  {
    printf("r:文件打开失败!\n");
  }
  else
  {
    printf("r:文件打开成功!\n");
    fclose(read);
  }
  FILE* write = fopen("write.txt", "w");
  if (write == NULL)
  {
    printf("w:文件打开失败!\n");
  
  }
  else 
  {
    printf("w:文件打开成功!\n");
    fclose(write);
  }
  FILE* append = fopen("append.txt", "a");
  if (append == NULL)
  {
    printf("a:文件打开失败!\n");
  }
  else
  {
    printf("a:文件打开成功!\n");
    fclose(append);
  }
  return 0;
}

程序运行结果如下:

文件操作| 文件读写

字符方式读写

字符读写使用下面两个函数完成:

int fputc(int _Character,FILE* _Stream):文件字符写操作

  • _Character:写的字符
  • _Stream:写的文件
  • 返回值:写入的字符

int (FILE* _Stream):文件字符读操作。

  • _Stream:读的文件
  • 返回值:读取的字符

案例代码如下:

#include <stdio.h>
//保存文件
void saveFile(const char* str) 
{
  FILE* fp = fopen("info.txt", "w");
  int i = 0;
  while (str[i] != '\0')
  {
    printf("%c\n",fputc(str[i], fp));
    i++;
  }
  fclose(fp);
}
//读取文件并显示
void readFile() 
{
  FILE* fp = fopen("info.txt", "r");
  if (fp == NULL) 
  {
    printf("文件打开失败!\n");
    return;
  }
  int userKey = fgetc(fp);
  while (userKey != EOF) 
  {
    putchar(userKey);
    userKey = fgetc(fp);
  }
  fclose(fp);
}
int main()
{
  char str[] = { "coolmoying" };
  saveFile(str);
  readFile();
  return 0;
}

运行结果如下:

字符串方式读写

字符串读写使用下面两个函数完成:

int fputc(int _Character,FILE* _Stream):文件字符写操作

  • _Character:写的字符
  • _Stream:写的文件返回值:写入的字符

int (FILE* _Stream):文件字符读操作。

  • _Stream:读的文件
  • 返回值读取的字符

案例代码如下:

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
//保存文件
void saveFile(const char* str) 
{
  FILE* fp = fopen("info.txt", "w");
  //写入多行
  fputs(str, fp);
  fputs(str, fp);
  fclose(fp);
}
//读取文件并显示
void readFile() 
{
  FILE* fp = fopen("info.txt", "r");
  if (fp == NULL) 
  {
    printf("文件打开失败!\n");
    return;
  }
  char buffer[1024] = { "" };
  while (fgets(buffer, 10, fp)!=NULL)
  {
    printf("%s", buffer);
  }
  fclose(fp);
}
int main()
{
  char str[] = { "coolmoying\n" };
  saveFile(str);
  readFile();
  return 0;
}

运行结果如下:

格式化方式读写

格式化读写使用下面两个函数完成:

int fprintf(FILE* _Stream,char const* _Format,…):文件格式化写操作

  • _Stream:写的文件,当第一个参数是stdout 和printf一样的功能
  • _Format,…:格式控制,类似printf函数参数
  • 返回值:写入的字符个数

int fscanf(FILE* _Stream,char const* _Format,…):文件格式化读操作。

  • _Stream:读的文件,当第一个参数是stdin和scanf函数一样的功能
  • _Format,…:格式控制,类似scanf函数参数
  • 返回值读取的成功的数据个数,读取到文件末尾返回EOF

通常格式化读写可以用来读写结构体数据,表格数据读写非常方便,案例代码如下:

#include <stdio.h>
#include <string.h>
struct MM 
{
  char name[20];
  int age;
  double money;
};
//结构体数组写操作
void saveFile(struct MM array[], int arrayNum) 
{
  FILE* fp = fopen("test.txt", "w");
  for (int i = 0; i < arrayNum; i++) 
  {
    fprintf(fp, "%s\t%d\t%.1lf\n", 
      array[i].name, array[i].age, array[i].money);
  }
  fclose(fp);
}
//结构体数组读操作
void readFile() 
{
  FILE* fp = fopen("test.txt", "r");
  struct MM temp;
  //文件读操作不需要格式控制
  while (fscanf(fp, "%s\t%d\t%lf\n",
    temp.name, &temp.age, &temp.money) != EOF) 
  {
    //可以存储到数组中,这里直接打印
    printf("%s\t%d\t%.1lf\n",
      temp.name, temp.age, temp.money);
  }
  fclose(fp);
}
int main()
{
  struct MM array[3] = {
    {"moying",18,100},
    {"girl",28,98},
    {"mm",18,78} };
  saveFile(array, 3);
  readFile();
  return 0;
}

运行结果如下:

二进制方式读写

二进制读写使用下面两个函数完成:

size_t fwrite(void const* _Buffer,size_t* _ElementSize,size_t* _ElementCount,FILE* _Stream):文件格式化写操作

  • _Buffer:被写入数据的首地址
  • _ElementSize:每次写入的大小
  • _ElementCount:几次写入_Stream:写的文件
  • 返回值:_ElementCount

size_t fread(void const* _Buffer,size_t* _ElementSize,size_t* _ElementCount,FILE* _Stream):文件格式化读操作。

  • _Buffer:读到指定内存的首地址
  • _ElementSize:每次读取的大小
  • _ElementCount:读取的份数
  • _Stream:读的文件
  • 返回值:_ElementCount

通常格式化读写可以用来读写结构体数据非常方便,文件中数据可能存在乱码,能成功读出来即可,读写打开文件方式一定要记得带b走,案例代码如下:

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
struct MM 
{
  char name[20];
  int age;
  double money;
};
//结构体数组写操作
void saveFile(struct MM array[], int arrayNum) 
{
  FILE* fp = fopen("test.txt", "wb");
  int result=fwrite(array, sizeof(struct MM), arrayNum, fp);
  fclose(fp);
}
//结构体数组读操作
void readFile() 
{
  FILE* fp = fopen("test.txt", "rb");
  struct MM temp = {0};
  //通常用返回值作判定,不用数组长度,数据未知
  while (fread(&temp, sizeof(struct MM), 1, fp)!=0)
  {
    //可以转存到指定数组中,这里只做打印测试
    printf("%s\t%d\t%.lf\n", temp.name, temp.age, temp.money);
  }
  fclose(fp);
}
int main()
{
  struct MM array[3] = {
    {"moying",18,100},
    {"girl",28,98},
    {"mm",18,78} };
  saveFile(array, 3);
  readFile();
  return 0;
}

运行结果如下

文件操作| 文件指针移动

C语言文件指针在文件读写过程中都是内部实现移动过程,一个文件指针写完数据到达文件末尾,直接进行读取操作,不能读出任何东西。C语言提供了一些操作文件指针函数,主要有以下这些

void rewind(FILE* _Stream):把文件指针还原到文件开头

  • _Stream:还原的文件指针

void fseek(FILE* _Stream,long _Offset,int _Origin):移动文件指针

  • _Stream:移动的文件指针
  • _Offset:相对于参照点的偏移量
  • _Origin:参照点
  • SEEK_SET:文件开头
  • SEEK_CUR:当前位置
  • SEEK_END:文件结束通常适用于二进制读写中实现指定数据读写

long fseek(FILE* _Stream):统计文件指针移动字节数

示例程序| 获取文件大小

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

int getFileSize(const char* filename) 
{
  FILE* fp = fopen(filename, "r+");
  if (fp == NULL)
    return 0;
  fseek(fp, 0L, SEEK_END);
  int size = ftell(fp);
  fclose(fp);
  return size;
}
int main()
{
  printf("size:%d\n", getFileSize("./wegame.exe"));
  return 0;
}

运行结果如下

C语言文件重定向操作

文件重定向是一种将程序的输入和输出源更改为文件的操作。可以使用重定向操作符 <> 来实现文件重定向。其中 < 运算符用于指定程序的输入数据来源为一个文件,而 > 运算符用于将程序的输出结果写入到一个文件中。重定向操作符后可跟文件路径,表示要将输入或输出流重定向到该文件。C语言提供了以下函数实现文件重定向:

FILE* freopen(char const* _FileName,char const* _Mode,FILE* _Stream):文件重定向

  • _FileName:定向的文件CON:重定向恢复到控制台
  • _Mode:读写方式
  • _Stream:定向的内容 stdin:定向标准输入 stdout:定向标准输出

示例程序| 文件重定向

#include <stdio.h>
int main() 
{
    FILE* ouput = freopen("output.txt", "w", stdout);
    //会输出到文件里
    puts("coolmoying");
    putchar('A');
    fprintf(stderr, "error\n");  //标准错误,不能重定向,只能输出到黑窗口

    FILE* input = freopen("input.txt", "r", stdin);
    if (!ouput)
    {
        perror("重定向失败!\n");
    }
    int a = 0, b = 0;
    //文件中的数据完成输入
    scanf("%d%d", &a, &b);
    //定向恢复
    ouput = freopen("CON", "w", stdout);
    if (!ouput)
    {
        perror("重定向恢复失败!\n");
    }
    printf("sum=%d\n", a + b);
  return 0;
}

运行结果如下

相关推荐

Nginx 响应提速10倍,你需要知道的缓存性能优化——FastCGI调优
Nginx 响应提速10倍,你需要知道的缓存性能优化——FastCGI调优

Nginx缓存优化是帮助大家提升网站性能的重要操作之一,proxy_cache主要用于反向代理时,对后端内容源服务器进行缓存;fastcgi_cache主要用于...

2024-05-20 14:44 gowuye

王者荣耀天魔缭乱和逐梦之音返场活动地址 3月22日开启返场活动
王者荣耀天魔缭乱和逐梦之音返场活动地址 3月22日开启返场活动

王者荣耀官方终于确定了天魔缭乱和逐梦之音的返场活动,这让不少小伙伴乐开了花,返场活动将会在3月22日开启,下面就带来王者荣耀天魔缭乱和逐梦之音返场活动地址!王者...

2024-05-20 14:44 gowuye

常见的嵌入式web服务器有哪些?

嵌入式WEB服务器常见的有:Lighttpd,Shttpd,Thttpd,Boa,Mini_httpd,Appweb,Goahead。Lighttpd地址:http://www.light...

简述几款常见的嵌入式web服务器
简述几款常见的嵌入式web服务器

嵌入式web服务器,是web服务器当中的一种,是基于嵌入式系统而实现的web服务器。指的是在嵌入式系统(通俗点就是单片机系统)上实现的一个web服务器,可以通过...

2024-05-20 14:44 gowuye

教你如何利用fastcgi_cache缓存加速WordPress

在使用nginx缓存之前,必须在nginx里面加载专门的模块,这个模块叫做ngx_cache_purge。添加ngx_cache_purge模块下载ngx_cache_purge模块ngx_cache...

扫描WordPress漏洞

检测已知漏洞WPScan是一款广泛使用的WordPress安全扫描工具,它的一项重要功能是检测已知漏洞。在这篇文章中,我们将深入探讨WPScan如何检测已知漏洞,并结合实际示例,帮助读者更好地理解和应...

消灭 Bug!推荐几个给力的开源 Bug 跟踪工具
消灭 Bug!推荐几个给力的开源 Bug 跟踪工具

在这个充满bug的世界里,最遥远的距离不是生与死,而是你亲手制造的bug就在你眼前,你却怎么都找不到它。因此本文准备了7款优秀的开源bug跟踪系...

2024-05-20 14:43 gowuye

生物信息分析入门全攻略

生物信息学是生命科学研究的重大前沿领域,未来将占据生命科学研究的半壁江山。已经有越来越多的小伙伴投入到生物信息的学习中,但是入门难、深入慢、摸不到方向等都成为持续学习的拦路虎。本文根据生物信息技术大牛...

elkb实践经验,再赠送一套复杂的配置文件
elkb实践经验,再赠送一套复杂的配置文件

原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处。宝剑锋从磨砺出,梅花香自苦寒来。诗人白居易,三月下江南,看到沿路开放的桃花,心潮澎湃...

2024-05-20 14:43 gowuye

超详细从0到1 搭建ELK监控
超详细从0到1 搭建ELK监控

监控分类?Metrics用于记录可聚合的数据。例如,1、队列的当前深度可被定义为一个度量值,在元素入队或出队时被更新;HTTP请求个数可被定义为一个计数器,...

2024-05-20 14:42 gowuye

嵌入式开发 之Web配置页面开发
嵌入式开发 之Web配置页面开发

1.PHP是最好的语言??开发动态页面首选的语言是PHP,村村不能在这里忽悠人,如果你的硬件性能允许切略懂PHP,看到这里就可以退出了。本文面向的受众是Linu...

2024-05-20 14:42 gowuye

Python开发一个网站目录扫描工具用来检测网站是否有漏洞?
Python开发一个网站目录扫描工具用来检测网站是否有漏洞?

开发一个网站目录扫描工具是用来检测网站是否有非法目录请求的一个常见需求之一,我们要通过这个扫描工具来找到通过某个域名可以访问到的网站路径,可能对于有些系统来讲,...

2024-05-20 14:42 gowuye

创建一个类似Youtube的Id——使用PHP/Python/JS/Java/SQL

id通常都是用数字,不巧的是只有10个数字来使用,所以如果你有很多的记录,id往往变得非常冗长。当然对于计算机来说无所谓,但我们更希望id尽可能短。所以我们如何能使id变短?我们可以利用字母让它们附加...

快速云:有助于移动应用安全开发的五条妙计
快速云:有助于移动应用安全开发的五条妙计

许多企业不断地向其开发团队提供培训。但是某些漏洞,如早在十多年前就发现的SQL注入,如今仍广泛存在于各种应用中。因而,安全培训永不过时。在开发移动应用时,开发者...

2024-05-20 14:41 gowuye

洛杉矶国际电影节最佳动画短片奖影片《G’DAY》正式全网上映
洛杉矶国际电影节最佳动画短片奖影片《G’DAY》正式全网上映

7月2日,由M&CSaatchi创作,由深受好评的澳大利亚导演迈克尔·格雷西执导的动画短片《G’day》,正式在全网上映。该影片因其出色的创意赢得了洛...

2024-05-20 14:41 gowuye

取消回复欢迎 发表评论: