【文件操作:解锁高效读写与管理技巧】(中)

简介: 【文件操作:解锁高效读写与管理技巧】

【文件操作:解锁高效读写与管理技巧】(上):https://developer.aliyun.com/article/1424823


那么再来写练一下文本行输出函数


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


  • 将由 str 指向的 C 字符串写入流中。
  • 该函数从指定地址(str)开始复制,直到遇到终止空字符('\0')为止。终止空字符不会被复制到流中。
  • 注意,fputs 与 puts 的区别不仅在于可以指定目标流,而且 fputs 不会写入额外的字符,而 puts 会自动在末尾追加换行字符。


#include<stdio.h>
int main()
{
  FILE* pf = fopen("data.txt","w");
  if (!pf)
  {
    perror("fopen");
    return 1;
  }
  //写文件 - 写一行 - 输出
  //int fputs ( const char * str, FILE * stream );
  fputs("hello world\n",pf);
  fputs("big dream\n", pf);
  //这两句话在文件中是一行还是两行? 两行
  //关闭文件
  fclose(pf);
  pf = NULL;
  return 0;
}


输出结果:



文本输入函数:


int fgetc ( FILE * stream );


  • 返回指定流的内部文件位置指示器当前指向的字符。然后,内部文件位置指示器会向下一个字符推进。
  • 如果在调用时流已经到达文件末尾,该函数返回 EOF 并为该流设置文件末尾指示器 (feof)。
  • 如果发生读取错误,该函数返回 EOF 并为该流设置错误指示器 (ferror)。
  • fgetc 和 getc 是等价的,但在某些库中 getc 可能被实现为宏。


#include<stdio.h>
int main()
{
  FILE* pf = fopen("data.txt","r");
  if (!pf)
  {
    perror("fopen");
    return 1;
  }
  //读文件 - 读一行 - 输入
  //char * fgets ( char * str, int num, FILE * stream );
  char arr[10] = { 0 };
  fgets(arr, 10, pf);
  printf("%s\n", arr);
  //关闭文件
  fclose(pf);
  pf = NULL;
  return 0;
}


运行结果:



       上面的结果发现输出了两个换行,说明fgets在获取到num-1(留一个位置给'\n')个字符之后会自动换行。如果该字符没有读完,下次读取就会取消第一次读取的换行,将第二次的输出字符,直至这个字符串读完再换行。


格式输出函数:


int fprintf ( FILE * stream, const char * format, ... );


  • 将由 format 指向的 C 字符串写入流中。如果 format 包含格式说明符(以 % 开头的子序列),则会格式化并插入 format 后面的附加参数,替换相应的格式说明符。
  • 在 format 参数之后,该函数期望至少有与 format 指定的格式相同数量的附加参数。


#include<stdio.h>
int main()
{
  FILE* pf = fopen("data.txt","w");
  if (!pf)
  {
    perror("fopen");
    return 1;
  }
  //写文件  - 输出
  //int fprintf ( FILE * stream, const char * format, ... );
  fprintf(pf,"%d %lf",520,13.14);
  //关闭文件
  fclose(pf);
  pf = NULL;
  return 0;
}


结果:



格式输入函数


int fscanf ( FILE * stream, const char * format, ... );


  • 从流中读取数据,并根据参数 format 将它们存储到附加参数所指向的位置。
  • 附加参数应该指向已经分配的对象,其类型由 format 字符串中对应的格式说明符指定。


#include<stdio.h>
int main()
{
  int a;
  double d;
  FILE* pf = fopen("data.txt","r");
  if (!pf)
  {
    perror("fopen");
    return 1;
  }
  //读文件  - 输入
  //int fscanf ( FILE * stream, const char * format, ... );
  fscanf(pf, "%d %lf", &a, &d);
  //关闭文件
  fclose(pf);
  pf = NULL;
  return 0;
}


二进制输出:


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


  • 将由 ptr 指向的内存块中的 count 个元素写入流的当前位置。
  • 流的位置指示器会根据写入的总字节数向前推进。
  • 在内部,该函数将 ptr 指向的块解释为类型为 unsigned char 的 (size*count) 个元素的数组,并按顺序将它们写入流中,就像对每个字节调用了 fputc 一样。


#include<stdio.h>
struct S
{
  int a;
  double d;
};
int main()
{
  struct S s = { 520,13.14 };
  FILE* pf = fopen("data.txt", "wb");//二进制打开文件
  if (!pf)
  {
    perror("fopen");
    return 1;
  }
  //写文件 - 输出
  //size_t fwrite(const void* ptr, size_t size, size_t count, FILE * stream);
  fwrite(&s, sizeof(struct S), 1, pf);
  //关闭文件
  fclose(pf);
  pf = NULL;
  return 0;
}


输出:二级制文件



二进制输入:



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


  • 从流中读取 count 个元素,每个元素大小为 size 字节,并将它们存储在由 ptr 指定的内存块中。
  • 流的位置指示器会根据成功读取的总字节数向前推进。
  • 如果成功读取,总共读取的字节数为 (size*count)。
#include<stdio.h>
struct S
{
  int a;
  double d;
};
int main()
{
  struct S s = { 0 };
  FILE* pf = fopen("data.txt", "rb");//二进制读出文件
  if (!pf)
  {
    perror("fopen");
    return 1;
  }
  //读文件 - 输入
  //size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
  fread(&s, sizeof(struct S), 1, pf);
  printf("%d %lf", s.a, s.d);
  //关闭文件
  fclose(pf);
  pf = NULL;
  return 0;
}


运行结果:



4.2 对比一组函数:


int sscanf ( const char * s, const char * format, ...);


  • 从字符串 s 中读取数据,并根据参数 format 将其存储到附加参数所指向的位置,就像使用 scanf 一样,但是从字符串 s 而不是标准输入(stdin)读取。
  • 附加参数应该指向已经分配的对象,其类型由 format 字符串中对应的格式说明符指定。


int sprintf ( char * str, const char * format, ... );


  • 该函数将以与使用 printf 时相同的文本组成一个字符串,但不会将其打印,而是将内容存储为 C 字符串,存放在由 str 指向的缓冲区中。
  • 缓冲区的大小应足够大,以容纳整个结果字符串(请参阅更安全的版本 snprintf)。
  • 内容后会自动追加一个终止空字符。
  • 在 format 参数之后,该函数期望至少有足够的附加参数以满足 format 的需求。


#include<stdio.h>
struct S
{
  int a;
  double d;
  char arr[10];
};
int main()
{
  struct S s = { 12,3.14,"hello" };
  char str[100];
  struct S temp = { 0 };
  //int sprintf ( char * str, const char * format, ... );
  sprintf(str, "%d %lf %s", s.a, s.d, s.arr);
  printf(str);
  //int sscanf ( const char * s, const char * format, ...);
  sscanf(str, "%d %lf %s", &(temp.a), &(temp.d), &(temp.arr));
  printf("%d %lf %s\n", temp.a, temp.d, temp.arr);
  return 0;
}


  1. scanf, fscanf, sscanf:


scanf: 从标准输入(键盘)读取数据,并根据指定的格式进行解析,将数据存储到给定的变量中。

fscanf: 从指定的文件流中读取数据,并根据指定的格式进行解析,将数据存储到给定的变量中。

sscanf: 从指定的字符串中读取数据,并根据指定的格式进行解析,将数据存储到给定的变量中。


  1. printf, fprintf, sprintf:


printf: 将格式化的数据输出到标准输出(屏幕)。

fprintf: 将格式化的数据输出到指定的文件流。

sprintf: 将格式化的数据输出到指定的字符串缓冲区。


总结区别:


scanf, fscanf, sscanf 主要用于输入操作,从不同来源(标准输入、文件、字符串)读取数据。

printf, fprintf, sprintf 主要用于输出操作,将格式化的数据输出到不同的目标(标准输出、文件、字符串缓冲区)中。


5. 文件的随机读写


5.1 fseek - 根据文件指针的位置和偏移量来定位文件指针。


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


stream:指向标识流的 FILE 对象的指针。


offset:


  • 二进制文件:从 origin 确定的位置偏移的字节数。
  • 文本文件:要么为零,要么为 ftell函数 返回的值。


origin:用作偏移参考的位置。


  • SEEK_SET 文件开头
  • SEEK_CUR 文件指针的当前位置
  • SEEK_END 文件末尾
#include <stdio.h>
int main()
{
  FILE* pFile;
  pFile = fopen("example.txt", "wb");
  fputs("This is an apple.", pFile);///写文件 - 输出
  fseek(pFile, 9, SEEK_SET);//从起始位置开始偏移
  //fseek(pFile, -8, SEEK_END);//从起始位置开始偏移
  //偏移量为9的字符串换为 sam
  fputs(" sam", pFile);///写文件 - 输出
  fclose(pFile);
  pFile = NULL;
  return 0;
}


运行结果:



【文件操作:解锁高效读写与管理技巧】(下):https://developer.aliyun.com/article/1424833

相关文章
|
9月前
|
负载均衡 Java Nacos
常见的Ribbon/Spring LoadBalancer的负载均衡策略
自SpringCloud 2020版起,Ribbon被弃用,转而使用Spring Cloud LoadBalancer。Ribbon支持轮询、随机、加权响应时间和重试等负载均衡策略;而Spring Cloud LoadBalancer则提供轮询、随机及Nacos负载均衡策略,基于Reactor实现,更高效灵活。
609 0
|
Python
Python运算符学习应用案例详解
Python运算符包括算术、比较、逻辑、位、赋值、成员和身份运算符。算术运算符如+、-、*、/、%和**;比较运算符如==、!=、&gt;、&lt;等;逻辑运算符有and、or和not;位运算符涉及按位与、或、异或及移位;赋值运算符如=、+=等;成员运算符in和not in检查元素是否在序列中;身份运算符is和is not判断对象引用。示例代码展示了这些运算符的用法。
84 1
|
存储 缓存
浏览器缓存sessionStorage、localStorage、Cookie
浏览器缓存sessionStorage、localStorage、Cookie
171 1
|
算法
LeetCode 数据结构与算法之矩阵置零
LeetCode 数据结构与算法之矩阵置零
167 0
LeetCode 数据结构与算法之矩阵置零
|
JSON 运维 前端开发
分享 10个我常逛的国外技术社区,真的受益匪浅!
国内技术博客满足不了你?那来看看这些吧!
3886 0
分享 10个我常逛的国外技术社区,真的受益匪浅!
|
人工智能 移动开发 安全
数字化浪潮来袭,金融机构如何“乘风破浪”?
在CFCA举办的“2020中国金融科技创新大赛中,蚂蚁集团移动开发平台mPaaS和金融级分布式架构SOFAStack荣获“综合智能平台金奖”。
数字化浪潮来袭,金融机构如何“乘风破浪”?
|
Oracle MySQL 关系型数据库
MySQL 5.6 升级到MySQL 5.7
随着MySQL 5.7越来越稳定,以及MySQL 5.7的新特性的吸引,MySQL 5.6以及无法满足部分人的需求了,决定使用MySQL 5.7。 MySQL 5.6如何升级到MySQL 5.7就是一个不可避免的问题。
19624 0
|
移动开发 JavaScript 前端开发
Animo.js :一款管理 CSS 动画的强大的小工具
  Animo.js 是一个功能强大的小工具,用于管理 CSS 动画。它的特色功能包括像堆栈动画,创建跨浏览器的模糊,设置动画完成的回调等等。Animo 还包括惊人的 animate.css,为您提供了近60个美丽的动画,还加入了一些辅助动画到库中。
1204 0