【《C Primer Plus》读书笔记】第13章:文件输入/输出

news2025/7/18 14:11:48

【《C Primer Plus》读书笔记】第13章:文件输入/输出

  • 13.1 与文件进行通信
    • 13.1.1 文件是什么
    • 13.1.2 文本模式和二进制模式
    • 13.1.3 I/O的级别
    • 13.1.4 标准文件
  • 13.2 标准I/O
  • 13.3 一个简单的文件压缩程序
  • 13.4 文件I/O:fprintf()、fscanf()、fgets()和fputs()
  • 13.5 随机访问:fseek()和ftell()
    • C 库函数 - fseek()
    • C 库函数 - ftell()
    • reverse.c

13.1 与文件进行通信

13.1.1 文件是什么

文件通常是在磁盘或固态硬盘上的一段已命名的存储区。

C把文件看作是一系列连续的字节,每个字节都能被单独读取。

C提供两种文件模式:文本模式二进制模式

13.1.2 文本模式和二进制模式

所有文件的内容(在磁盘上)都以二进制(0或1)表示。

因为编码方式不同,导致展现的形式不同。

定义

  • 如果文件使用二进制编码的字符,如Unicode,ASCII表示文本,那么就是文本文件。
  • 如果二进制代表的是机器语言,或数值数据,或图片,或音乐编码,该文件就是二进制文件。

区别

  1. 对于字符串中\n的处理不同。
    在Windows系统中用文本模式打开文件时会发现文件中的换行符是\n,这看起来再正常不过了,但当你改为用二进制模式打开文件时会发现文件中的换行符变为\r\n
    事实上,在Windows系统中的的文件中的换行符都是\r\n,只不过在使用文本模式时,会把文件内容从文本的系统表示法映射为C表示法,而使用二进制表示法时不会进行映射转换。

  2. 以二进制模式打开文件是,可以逐字节读取文件。
    这也就是为什么在使用部分函数例如fseek()和ftell()时必须以二进制模式打开文件

  3. 使用文本模式打开文件时,就要用fprintf()写入数据,使用二进制模式打开文件时候,就要用fwrite()写入数据。
    这是因为fprintf()类型的函数会将数据转换为文本,而fwrite()这类函数则不会。

为了规范文本文件的处理,C提供两种访问文件的途径:文本模式二进制模式

  • 在二进制模式中,程序可以访问文件的每个字节。
  • 在文本模式中,程序所见的内容与文件实际内容不同。典型代表就是对于字符串中\n的处理。

13.1.3 I/O的级别

  • 底层I/O:使用操作系统的基本I/O服务。
  • 标准高级I/O:使用C库的标准包和stdio.h头文件定义。

C标准只支持标准I/O包。有些实现会提供底层库,但C标准建立了可移植的I/O模型。

13.1.4 标准文件

C程序会自动打开3个文件:标准输入、标准输出、标准错误输出。

标准输入是系统的普通输入设备,通常是键盘。

标准输出、标准错误输出是系统的普通输出设备,通常是显示屏。

标准错误输出提供了一个从逻辑上不同的地方来发送错误的信息。

13.2 标准I/O

标准I/O由ANSI C标准定义,C标准中定义了C库,标准I/O就是C库中用来输入和输出的函数。标准I/O在系统调用的上一层多加了一个缓冲区,通过缓冲机制减少了系统调用,实现更高的效率。

标准I/O包的3个好处:

  1. 可移植
  2. 标准I/O有许多专门的函数简化了处理不同I/O的问题
  3. 输入和输出都是缓冲

程序清单13.1 count.c程序

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    int ch;
    FILE *fp;
    unsigned count = 0;
    if (argc != 2)
    {
        printf("Usage: %s filename\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    if ((fp = fopen(argv[1], "r")) == NULL)
    {
        printf("Can't open %s\n", argv[1]);
        exit(EXIT_FAILURE);
    }
    while ((ch = getc(fp)) != EOF)
    {
        putc(ch, stdout);
        count++;
    }
    fclose(fp);
    printf("File %s has %lu characters\n", argv[1], count);

    system("pause");
    return 0;
}

13.3 一个简单的文件压缩程序

程序清单13.2 reducto.c程序

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 40

int main(int argc, char *argv[])
{
    FILE *in, *out;
    int ch;
    char name[LEN];
    int count = 0;

    if (argc < 2)
    {
        fprintf(stderr, "Usage: %s filename\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    if ((in = fopen(argv[1], "r")) == NULL)
    {
        fprintf(stderr, "I couldn't open the file \"%s\"\n", argv[1]);
        exit(EXIT_FAILURE);
    }
    strncpy(name, argv[1], LEN - 5);
    name[LEN - 5] = '\0';
    strcat(name, ".red");
    if ((out = fopen(name, "w")) == NULL)
    {
        fprintf(stderr, "Can't create output file.\n");
        exit(3);
    }
    while ((ch = getc(in)) != EOF)
        if (count++ % 3 == 0)
            putc(ch, out);
    if (fclose(in) != 0 || fclose(out) != 0)
        fprintf(stderr, "Error in closing files\n");
    
    system("pause");
    return 0;
}

运行结果:

在这里插入图片描述

在这里插入图片描述

13.4 文件I/O:fprintf()、fscanf()、fgets()和fputs()

程序清单13.3 addword.c程序

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 41

int main(void)
{
    FILE *fp;
    char words[MAX];

    if ((fp = fopen("wordy", "a+")) == NULL)
    {
        fprintf(stderr, "Can't open \"wordy\" file.\n");
        exit(EXIT_FAILURE);
    }

    puts("Enter words to add to the file; press the #");
    puts("key at the beginning of a line to terminate.");
    while ((fscanf(stdin, "%40s", words) == 1) && (words[0] != '#'))
        fprintf(fp, "%s\n", words);
    
    puts("File contents:");
    rewind(fp); /*返回到文件开始处*/
    while (fscanf(fp, "%s", words) == 1)
        puts(words);
    puts("Done!");
    if (fclose(fp) != 0)
        fprintf(stderr, "Error closing file\n");
    
    system("pause");
    return 0;
}

运行结果:

在这里插入图片描述

在这里插入图片描述

13.5 随机访问:fseek()和ftell()

C 库函数 - fseek()

描述
C 库函数 int fseek(FILE *stream, long int offset, int whence) 设置流 stream 的文件位置为给定的偏移 offset,参数 offset 意味着从给定的 whence 位置查找的字节数。

声明
下面是 fseek() 函数的声明。

int fseek(FILE *stream, long int offset, int whence)

参数

  • stream – 这是指向 FILE 对象的指针,该 FILE 对象标识了流。
  • offset – 这是相对 whence 的偏移量,以字节为单位。
  • whence – 这是表示开始添加偏移 offset 的位置。它一般指定为下列常量之一:
常量描述
SEEK_SET文件的开头
SEEK_CUR文件指针的当前位置
SEEK_END文件的末尾

返回值
如果成功,则该函数返回零,否则返回非零值。

实例
下面的实例演示了 fseek() 函数的用法。

#include <stdio.h>

int main ()
{
   FILE *fp;

   fp = fopen("file.txt","w+");
   fputs("This is runoob.com", fp);
  
   fseek( fp, 7, SEEK_SET );
   fputs(" C Programming Langauge", fp);
   fclose(fp);
   
   return(0);
}

让我们编译并运行上面的程序,这将创建文件 file.txt,它的内容如下。最初程序创建文件和写入 This is runoob.com,但是之后我们在第七个位置重置了写指针,并使用 puts() 语句来重写文件,内容如下:

This is C Programming Langauge

现在让我们使用下面的程序查看上面文件的内容:

#include <stdio.h>

int main ()
{
   FILE *fp;
   int c;

   fp = fopen("file.txt","r");
   while(1)
   {
      c = fgetc(fp);
      if( feof(fp) )
      {
          break ;
      }
      printf("%c", c);
   }
   fclose(fp);
   return(0);
}

运行结果:

在这里插入图片描述

C 库函数 - ftell()

描述
C 库函数 long int ftell(FILE *stream) 返回给定流 stream 的当前文件位置,即:参数指向文件的当前位置距文件开始处的字节数。

声明:
下面是 ftell() 函数的声明。

long int ftell(FILE *stream)

参数
stream – 这是指向 FILE 对象的指针,该 FILE 对象标识了流。

返回值
该函数返回位置标识符的当前值。如果发生错误,则返回 -1L,全局变量 errno 被设置为一个正值。
返回类型为long。

实例
下面的实例演示了 ftell() 函数的用法。

#include <stdio.h>

int main ()
{
   FILE *fp;
   int len;

   fp = fopen("file.txt", "r");
   if( fp == NULL ) 
   {
      perror ("打开文件错误");
      return(-1);
   }
   fseek(fp, 0, SEEK_END);

   len = ftell(fp);
   fclose(fp);

   printf("file.txt 的总大小 = %d 字节\n", len);
   
   return(0);
}

假设我们有一个文本文件 file.txt,它的内容如下:

This is runoob.com

让我们编译并运行上面的程序,如果文件内容如上所示,这将产生以下结果,否则会根据文件内容给出不同的结果:

file.txt 的总大小 = 18 字节

运行结果:

This is runoob.com

reverse.c

程序清单13.4 reverse.c

逆序打印文件内容。

代码:

#include <stdio.h>
#include <stdlib.h>
#define CNTL_Z '\032' /* eof marker in DOS text files */
#define SLEN 81
int main(void)
{
    char file[SLEN];
    char ch;
    FILE *fp;
    long count, last;

    puts("Enter the name of the file to be processed:");
    scanf("%80s", file);
    if ((fp = fopen(file, "rb")) == NULL)
    { /* read-only mode   */
        printf("reverse can't open %s\n", file);
        exit(EXIT_FAILURE);
    }

    fseek(fp, 0L, SEEK_END); /* go to end of file */
    last = ftell(fp);
    for (count = 1L; count <= last; count++)
    {
        fseek(fp, -count, SEEK_END); /* go backward      */
        ch = getc(fp);
        if (ch != CNTL_Z && ch != '\r') /* MS-DOS files */
            putchar(ch);
    }
    putchar('\n');
    fclose(fp);

    return 0;
}

文件内容:

在这里插入图片描述

运行结果:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/369114.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【LVGL】学习笔记--(1)Keil中嵌入式系统移植LVGL

一 LVGL简介最近emwin用的比较烦躁&#xff0c;同时被LVGL酷炫的界面吸引到了&#xff0c;所以准备换用LVGL试试水。LVGL(轻量级和通用图形库)是一个免费和开源的图形库&#xff0c;它提供了创建嵌入式GUI所需的一切&#xff0c;具有易于使用的图形元素&#xff0c;美丽的视觉效…

极光笔记 | 埋点体系建设与实施方法论

PART 01 前 言随着网络技术的发展&#xff0c;从粗犷型到精细化运营型&#xff0c;再到现在的数字化运营&#xff0c;数据变得越来越细分和重要&#xff0c;不仅可以进行策略调整&#xff0c;还可以实现自动化的精细化运营。而数据价值的起点就是埋点&#xff0c;只有合理地埋点…

[计算机网络(第八版)]第一章 概述(学习笔记)

1.1 计算机网络在信息时代中的作用 21世纪是以网络为核心的信息时代&#xff0c;21世纪的重要重要特征&#xff1a;数字化、网络化与信息化。 三大类网络 电信网络&#xff1a;向用户提供电话、电报、传真等服务&#xff1b;有线电视网络&#xff1a;向用户传送各种电视节目&am…

zabbix4.0-使用zabbix监控别的主机-使用模板来创建图形

目录 1、 配置zabbix的yum源 2、下载zabbix-agent 3、配置zabbix-agent的配置文件 4、关闭防火墙&#xff0c;selinux 5、重启zabbix-agent 6、连通性测试&#xff0c;在zabbix-server服务器上面使用zabbix_get获取zabbix-agent服务器上的数据 7、在zabbix web端配置zab…

Windows 11 22H2 中文版、英文版 (x64、ARM64) 下载 (updated Feb 2023)

Windows 11, version 22H2&#xff0c;2023 年 2 月 更新 请访问原文链接&#xff1a;https://sysin.org/blog/windows-11/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;www.sysin.org 全新推出 Windows 11 全新 Windows 体验&#x…

考PMP的用处有哪些?备考攻略+资料分享

说到底&#xff0c;考PMP就是为了给工作提供便利&#xff0c;你考了之后会用它&#xff0c;将学习的东西运用到工作中&#xff0c;比如提高项目完成率&#xff0c;能升职加薪啊等等&#xff0c;那自然很是有用的。 不用&#xff0c;那就只是一张当摆设的纸&#xff0c;当然&am…

项目经理如何度量项目?及项目度量指标实例【静说】

度量项目是项目经理的一个重要职责&#xff0c;通过度量项目&#xff0c;项目经理可以了解项目的进展情况&#xff0c;及时发现问题并采取相应的措施&#xff0c;以确保项目能够按时、按质、按预算完成。 分享给大家一些常见的项目度量指标&#xff1a; 1. 项目进度&#xff…

docker-compose 简单配置php和nginx及注意事项

docker-compose.yml内容&#xff1a; /docker/web/config/nginx/conf/default.conf内容&#xff1a; server { listen 80; server_name localhost; root /usr/share/nginx/html; error_log /var/log/nginx/localhost.log; location / { try_files $…

ESP32-FPV-Camera介绍和使用

ESP32-FPV-Camera介绍和使用1. 编译目标2. 编译步骤Step 1 软件配置环境准备Step 2 获取开源代码Step 3 2.4G WiFi频段选择Step 4 要确保2.4G WiFi网卡处于Monitor状态Step 5 修改频点相关代码Step 6 修改WiFi网卡相关代码Step 7 OpenGL 版本问题Step 8 构建天空端Step 9 构建地…

从0开始写Vue项目-Vue实现用户数据批量上传和数据导出

从0开始写Vue项目-环境和项目搭建_慕言要努力的博客-CSDN博客从0开始写Vue项目-Vue2集成Element-ui和后台主体框架搭建_慕言要努力的博客-CSDN博客从0开始写Vue项目-Vue页面主体布局和登录、注册页面_慕言要努力的博客-CSDN博客从0开始写Vue项目-SpringBoot整合Mybatis-plus实现…

04--WXML

1、什么是WXML什么是Wxml呢&#xff1f;我们首先要介绍一下Html&#xff0c;Html的全称为HyperTextMarkup Language&#xff0c;翻译过来就是超文本标记语言&#xff0c;这种语言目前已经普遍用于前端开发&#xff0c;而wxml正是从html演变而来&#xff0c;它基于微信这个平台&…

4EVERLAND:ERC-721 Token的存储选择

4EVERLAND&#xff1a;一个 Web3 基础设施&#xff0c;可促进项目更轻松、更快速地托管前端、存储数据/NFT/文件&#xff0c;并在 IPFS、Arweave 和 Dfinity 之上访问它们。 NFT , 数字所有权 使用以太坊标准的 NFT 创新ERC-721解决了互联网内容的主要问题之一&#xff1a;所…

计算机网络(2)从十六进制的ip数据报中得到详细字段信息

本博文介绍如何将十六进制的ip报文拆分出具体的字段信息。社会计算机网络和网络协议分析的初学者参考&#xff08;今天看了网络协议分析期末复习重点的最后一个大题&#xff0c;竟然一头雾水&#xff0c;然后快马加鞭翻阅各种资料&#xff0c;然后差不多学会 了&#xff09;wir…

RK3568平台开发系列讲解(驱动基础篇)中断子系统框架

🚀返回专栏总目录 文章目录 一、中断硬件的组成二、软件框架三、中断常见概念沉淀、分享、成长,让自己和他人都能有所收获!😄 📢中断是指 CPU 正常运行期间,由于内外部事件或程序预先安排的事件,引起的 CPU 暂时停止正在运行的程序, 转而为该内部或外部预先安排的事…

零基础入门反序列化及常用trick

前言 反序列化是一个尤为重要的知识点&#xff0c;最近对反序列化进行了简单学习&#xff0c;并总结如下&#xff0c;希望能对正在学习的师傅有所帮助。 前提 了解序列化和反序列化 学习反序列化之前&#xff0c;首先要知道序列化&#xff0c;简单的举个栗子来说 <?ph…

C语言学习及复习笔记-【10】数组

10. 字符串 定义&#xff1a;在 C 语言中&#xff0c;字符串实际上是使用 null 字符 ‘\0’ 终止的一维字符数组。因此&#xff0c;一个以 null 结尾的字符串&#xff0c;包含了组成字符串的字符。 以下是 C/C 中定义的字符串的内存表示&#xff1a; 10.1 C 中有大量操作字符串…

Linux 脚本(sh)之 定时清理悬空、指定镜像,自动增长版本号

定时任务(images_clean)&#xff1a; 位置&#xff1a;/mydata/hostmachine_jenkins/images_clean.sh 作用&#xff1a;Jenkins发布之后&#xff0c;遗留下来的老版镜像以及悬空镜像进行定时清理 注意&#xff1a;如果你需要发布新的服务&#xff0c;那么你需要进入当前目录…

Git导出增量包的操作步骤

前言在项目开发部署中&#xff0c;通常是将一个Git项目全量打包发布&#xff0c;但有的场景只需要导出有变更的那部分文件&#xff0c;增量发布&#xff0c;此时就需要使用Git导出增量包了。一、查看提交记录拿到提交ID码①例如使用的gitlab使用方法参考下图(一目了然) 【推荐】…

利用机器学习(mediapipe),进行人手的21个3D手关节坐标检测

感知手的形状和动作的能力可能是在各种技术领域和平台上改善用户体验的重要组成部分。例如,它可以构成手语理解和手势控制的基础,并且还可以在增强现实中将数字内容和信息覆盖在物理世界之上。虽然自然而然地出现在人们手中,但是强大的实时手感知力无疑是一项具有挑战性的计…

【基础算法】字符串哈希

&#x1f339;作者:云小逸 &#x1f4dd;个人主页:云小逸的主页 &#x1f4dd;Github:云小逸的Github &#x1f91f;motto:要敢于一个人默默的面对自己&#xff0c;强大自己才是核心。不要等到什么都没有了&#xff0c;才下定决心去做。种一颗树&#xff0c;最好的时间是十年前…