首页 > 其他分享 >学习笔记2

学习笔记2

时间:2023-09-24 12:46:16浏览次数:38  
标签:文件 函数 int 笔记 学习 参数 FILE 权限

第九章 I/O库函数

一.知识点归纳

(一)I/O库函数与系统调用

  • 系统调用函数:open()、read()、write()、lseek()、close()
  • I/O库函数:fopen()、fread()、fwrite()、fseek()、fclose()

二者区别:

  1. 在系统调用程序中,文件描述符fd是一个整数。在库I/O程序中,fp是一个文件流指针。
  2. 系统调用open()打开一个文件进行读取,并返回一个整数文件描述符fd,如果open()失败,则返回-1。I/O库函数fopen()返回一个FILE结构体指针,如果fopen()失败,则返回NULL。
  3. 系统调用程序使用while循环读取/写入文件内容。在每个迭代中,它发出read()系统调用,将最多4KB的字符读入buf[]。然后,它将各字符从buf[]写到文件描述符1中,这是该进程的标准输出。正如前文所指出的,使用系统调用一次写入一个字节非常低效。相反,I/O库程序仅仅使用fgetc(fp)从文件流中获取字符,通过putchar()输出字符,直至文件结束符。

(二)I/O库函数的算法

1.fread算法

使用 fread() 对文件进行读操作,函数原型如下:

#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

参数和返回值含义:

参数 含义
ptr fread()将读取到的数据存放在参数 ptr 指向的缓冲区中
size fread()从文件读取 nmemb 个数据项,每一个数据项的大小为 size 个字节,所以总共读取的数据大小为 nmemb * size 个字节
nmemb 参数 nmemb 指定了读取数据项的个数
stream FILE 指针
返回值 调用成功时返回读取到的数据项的数目(数据项数目并不等于实际读取的字节数,除非参数size 等于 1);如果发生错误或到达文件末尾,则 fread()返回的值将小于参数 nmemb,那么到底发生了错误还是到达了文件末尾,fread()不能区分文件结尾和错误,究竟是哪一种情况,此时可以使用 ferror()或 feof()函数来判断

2.fwrite算法

fwrite() 库函数进行写操作,函数原型如下:

#include <stdio.h>
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

参数和返回值含义:

参数 含义
ptr 将参数 ptr 指向的缓冲区中的数据写入到文件中
size 参数 size 指定了每个数据项的字节大小,与 fread()函数的 size 参数意义相同
nmemb 参数 nmemb 指定了写入的数据项个数,与 fread()函数的 nmemb 参数意义相同
stream FILE 指针
返回值 调用成功时返回读取到的数据项的数目(数据项数目并不等于实际读取的字节数,除非参数size 等于 1);如果发生错误,则 fwrite()返回的值将小于参数 nmemb(或者等于 0)

3.fclose算法

打开的文件通过 fclose() 进行关闭,函数原型如下:

#include <stdio.h>
int fclose(FILE *stream);

4.fopen算法

使用fopen() 打开或创建文件,函数原型如下:

#include <stdio.h>
FILE *fopen(const char *path, const char *mode);

参数和返回值含义:

参数 含义
path 参数 path 指向文件路径,可以是绝对路径、也可以是相对路径
mode 参数 mode 指定了对该文件的读写权限,是一个字符串,稍后介绍
返回值 调用成功返回一个指向 FILE 类型对象的指针(FILE * ),该指针与打开或创建的文件相关联,后续的标准 I/O 操作将围绕 FILE 指针进行。如果失败则返回 NULL,并设置 errno 以指示错误原因
参数 mode 补充:
mode 说明
- -
r 以只读方式打开文件
r+ 以可读可写方式打开文件
w 以只写方式打开文件,如果参数path指定的文件存在,将文件长度截断为0,如果指定文件不存在 则创建该文件
w+ 以可读可写方式打开文件,如果参数path指定的文件存在,将文件长度截断为0;如果指定文件 不存在则创建该文件
a 以只写方式打开文件,打开以进行追加内容(在文件末尾写入),如果文件不存在则创建该文件 O_WRONLY
a+ 以可读可写方式打开文件,以追加方式写入 (在文件末尾写入),如果文件不存在则创建该文件

5.fseek算法和ftell算法

  • 库函数 fseek() 用于设置文件读写位置偏移量,和 lseek() 功能相同,但 lseek() 用于文件 I/O,而库函数 fseek() 则用于标准 I/O,函数原型:
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);

参数和返回值含义:

参数 含义
stream FILE 流指针
offset 与 lseek() 函数的 offset 参数意义相同,相对偏移位置的偏移值
whence 与 lseek()函数的 whence 参数意义相同,偏移位置
返回值 成功返回 0;发生错误将返回-1,并且会设置 errno 以指示错误原因;与 lseek()函数的返回值意义不同,这里要注意
  • 库函数 ftell() 可用于获取文件当前的读写位置偏移量,函数原型如下:
#include <stdio.h>
long ftell(FILE *stream);

参数 stream 指向对应的文件,函数调用成功将返回当前读写位置偏移量;调用失败将返回-1,并会设置 errno 以指示错误原因

(三)字符模式I/O

int fgetc(FILE *fp);		// get a char from fp, cast to int.
int ungetc(int c,FILE *fp);	// push a previously char got by fgetc()	back to stream
int fputc(int c,FILE *fp);	// put a char to fp

(四)行模式I/O

char *fgets(char *buf,int size,FILE *fp): 从fp中读取最多一行(以\n结尾)的字符。
int fputs(char *buf,FILE *fp): 将buf中的一行写入fp中。

(五)格式化I/O

  • 格式化输入

scanf(char *FMT,&item);		// from stdin
fscanf(fp,char *FMT,&items);	// from file stream
  • 格式化输出

printf(char *FMT,item);		// to stdout
fprintf(fp,char *FMT,items);	// to file stream

(六)内存中的转换函数

sscanf(buf,FMT,&items);		// input from buf[] in memory
sprintf(buf,FMT,items);		// print to buf[] in memory

二.问题与解决思路

1.argc、argv的具体含义是什么?

argc和argv参数在用命令行编译程序时有用。main( int argc, char* argv[], char** env ) 中:

  1. 第一个参数,int型的argc,为整型,用来统计程序运行时发送给main函数的命令行参数的个数,在VS中默认值为1。
  2. 第二个参数,char*型的argv[],为字符串数组,用来存放指向的字符串参数的指针数组,每一个元素指向一个参数。各成员含义如下:
    • argv[0]指向程序运行的全路径名
    • argv[1]指向在DOS命令行中执行程序名后的第一个字符串
    • argv[2]指向执行程序名后的第二个字符串
    • argv[3]指向执行程序名后的第三个字符串
    • argv[argc]为NULL
  3. 第三个参数,char** 型的env,为字符串数组。env[]的每一个元素都包含ENVVAR=value形式的字符串,其中ENVVAR为环境变量,value为其对应的值。平时使用到的比较少。

2.open()打开时flags传参O_RDONLY、O_WRONLY等的作用含义?

头文件:#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>

定义函数:

int open(const char * pathname, int flags);
int open(const char * pathname, int flags, mode_t mode);

函数说明:

  • 参数 pathname 指向欲打开的文件路径字符串. 下列是参数flags 所能使用的旗标:
    • O_RDONLY 以只读方式打开文件
    • O_WRONLY 以只写方式打开文件
    • O_RDWR 以可读写方式打开文件. 上述三种旗标是互斥的, 也就是不可同时使用, 但可与下列的旗标利用OR(|)运算符组合.
    • O_CREAT 若欲打开的文件不存在则自动建立该文件.
    • O_EXCL 如果O_CREAT 也被设置, 此指令会去检查文件是否存在. 文件若不存在则建立该文件, 否则将导致打开文件错误. 此外, 若O_CREAT 与O_EXCL 同时设置, 并且欲打开的文件为符号连接, 则会打开文件失败.
    • O_NOCTTY 如果欲打开的文件为终端机设备时, 则不会将该终端机当成进程控制终端机.
    • O_TRUNC 若文件存在并且以可写的方式打开时, 此旗标会令文件长度清为0, 而原来存于该文件的资料也会消失.
    • O_APPEND 当读写文件时会从文件尾开始移动, 也就是所写入的数据会以附加的方式加入到文件后面.
    • O_NONBLOCK 以不可阻断的方式打开文件, 也就是无论有无数据读取或等待, 都会立即返回进程之中.
    • O_NDELAY 同O_NONBLOCK.
    • O_SYNC 以同步的方式打开文件.
    • O_NOFOLLOW 如果参数pathname 所指的文件为一符号连接, 则会令打开文件失败.
    • O_DIRECTORY 如果参数pathname 所指的文件并非为一目录, 则会令打开文件失败。 注:此为Linux2. 2 以后特有的旗标, 以避免一些系统安全问题.
  • 参数mode 则有下列数种组合, 只有在建立新文件时才会生效, 此外真正建文件时的权限会受到umask 值所影响, 因此该文件权限应该为 (mode-umaks).

    • S_IRWXU00700 权限, 代表该文件所有者具有可读、可写及可执行的权限.
    • S_IRUSR 或S_IREAD, 00400 权限, 代表该文件所有者具有可读取的权限.
    • S_IWUSR 或S_IWRITE, 00200 权限, 代表该文件所有者具有可写入的权限.
    • S_IXUSR 或S_IEXEC, 00100 权限, 代表该文件所有者具有可执行的权限.
    • S_IRWXG 00070 权限, 代表该文件用户组具有可读、可写及可执行的权限.
    • S_IRGRP 00040 权限, 代表该文件用户组具有可读的权限.
    • S_IWGRP 00020 权限, 代表该文件用户组具有可写入的权限.
    • S_IXGRP 00010 权限, 代表该文件用户组具有可执行的权限.
    • S_IRWXO 00007 权限, 代表其他用户具有可读、可写及可执行的权限.
    • S_IROTH 00004 权限, 代表其他用户具有可读的权限
    • S_IWOTH 00002 权限, 代表其他用户具有可写入的权限.
    • S_IXOTH 00001 权限, 代表其他用户具有可执行的权限.
      返回值:若所有欲核查的权限都通过了检查则返回0 值, 表示成功, 只要有一个权限被禁止则返回-1.

三.苏格拉底挑战

用户

我在学习库I/O函数的算法知识点,请你以苏格拉底的方式对我进行提问

AI

当然,我会以苏格拉底的方式提问你关于库I/O函数的算法知识点。请回答下面的问题:

  1. 为什么在进行文件写入操作时,使用 fwrite() 函数比使用 fputs() 函数更适合处理二进制数据?
  2. 如何使用 fseek() 函数在文件中定位到指定的位置?
  3. 在处理大文件时,如何确定合适的缓冲区大小?缓冲区大小的选择与文件的大小有关吗?
  4. 在进行文件操作时,如何处理可能出现的错误?你可以举例说明一些常见的错误处理方法。
    请思考并回答这些问题,我将根据你的回答继续引导你的学习。

用户

  1. fwrite() 函数比 fputs() 函数更适合处理二进制数据的原因是 fwrite() 函数可以按照指定的大小将数据块写入文件,而 fputs() 函数是按照字符串进行写入。二进制数据可能包含任意的字节值,而字符串通常以 null 字符('\0')作为结束标志,因此在处理二进制数据时,使用 fwrite() 函数可以更灵活地写入指定大小的数据块。
  2. 使用 fseek() 函数可以在文件中定位到指定的位置。fseek() 函数的原型为:int fseek(FILE *stream, long int offset, int origin)。其中,stream 是文件指针,offset 是偏移量,origin 是偏移起点。常见的偏移起点有以下三种:
    SEEK_SET:从文件开头开始计算偏移量。
    SEEK_CUR:从当前位置开始计算偏移量。
    SEEK_END:从文件末尾开始计算偏移量。
    例如,要将文件指针定位到文件开头,可以使用 fseek(file, 0, SEEK_SET)。
  3. 在处理大文件时,确定合适的缓冲区大小需要综合考虑多个因素。一般来说,较大的缓冲区大小可以减少磁盘访问次数,提高读写效率。但是,缓冲区大小的选择不仅与文件的大小有关,还与系统内存大小、磁盘读写速度等因素有关。可以通过实验和性能测试来确定合适的缓冲区大小,找到一个平衡点,既能满足性能需求,又不会占用过多的内存资源。
  4. 在进行文件操作时,可能会出现各种错误,如文件不存在、权限不足、磁盘空间不足等。常见的错误处理方法包括:
    检查返回值:检查库I/O函数的返回值,如果返回值表示操作失败,可以根据具体情况采取相应的错误处理措施。
    错误码:一些库I/O函数会返回特定的错误码,可以根据错误码来判断和处理错误。
    异常处理:使用异常处理机制来捕获和处理可能发生的异常,以保证程序的稳定性。
    例如,在打开文件时,可以检查 fopen() 函数的返回值是否为 NULL,如果为 NULL,则表示打开文件失败,可以输出错误信息或者采取其他处理措施。

AI

非常好的回答!你对库I/O函数的算法知识点有了很好的理解。

用户

针对库I/O函数的算法知识,我了解了吗

AI

是的,你对库I/O函数的算法知识有了很好的理解。你正确地回答了关于不同函数之间的区别、适用场景以及错误处理方法等问题。你展示了对库I/O函数的理解和应用能力。
如果你还有其他问题或者需要进一步讨论其他主题,请随时告诉我。我将很乐意继续帮助你。

标签:文件,函数,int,笔记,学习,参数,FILE,权限
From: https://www.cnblogs.com/hosf/p/17725833.html

相关文章

  • 高级系统架构师学习(八)嵌入式系统
    一、嵌入式系统概述基本概念1、将可配置与可裁剪的软硬件集成于一体的专用计算机系统,需要满足应用对功能、可靠性、成本、体积和功耗等方面的严格要求。2、指嵌入各种设备及应用产品内部的计算机系统。它主要完成信号控制的功能。体积小、结构紧凑,可作为一个部件埋藏于......
  • vue笔记
    一、vue项目vscode自动import,VUE组件和ts模块1、在vscode插件市场安装vetur插件2、修改tsconfig.json文件将moduleResolution改为node3、重启vscode,后面再下代码就可以自动import了。二、vue项目中使用elementplus参考elementplus官网:https://element-plus.org/zh-CN/guide/desig......
  • 【机器学习 | 分类指标大全】全面解析分类评估指标:从准确率到AUC,多分类问题也不在话下
    ......
  • 第三周学习笔记
    sh编程1.sh脚本Shell脚本是一种用于在Unix、Linux和其他类Unix系统上编写和执行命令序列的脚本语言。它使用Shell解释器(如sh、bash、csh等)来解释和执行脚本。Shell脚本可以包含一系列命令、控制结构、变量和函数,用于完成特定的任务或自动化一系列操作。通过编写Shell脚本,你可以......
  • 学习笔记3
    第十章教材知识点Shell脚本:Shell脚本是一系列Shell命令的集合,以文本文件的形式保存,并通过Shell解释器执行。Shell脚本的文件扩展名通常为.sh。Shell脚本的第一行指定解释器,例如#!/bin/sh表示使用sh解释器。命令行参数:在Shell脚本中,可以通过特殊变量$0、$1、$2等来获......
  • 《Unix/Linux系统编程》教材第10章学习笔记
    大家学习过Python,C,Java等语言,总结一下一门程序设计语言有哪些必备的要素和技能?这些要素和技能在shell脚本中是如果呈现出来的?必备要素和技能:数据类型和变量:用于存储和处理数据的基本单元。控制结构:用于控制程序流程的结构,如条件语句、循环语句等。函数和模块:用于封装代码块......
  • 为什么要学习python技术??
    大家好,随着大数据时代的到来,相信大家对新时代的认知达到了一个新的高度,我们可以仔细观察我们的生活,似乎每一年都会发生较大的变化。我记得我刚上大学的时候,移动支付才刚开始普及,短短几年,出门只需要一部手机便能行走天下,其中计算机编程起到了重要作用。 我们为什么要学......
  • [笔记]$Python$输出笔记
    [笔记]\(Python\)输出笔记补位输出\(TypeI:\%\)格式化形式:\('format'\\\%\\'value'\)\(value\)可以是数字、字符串、变量等#数字型num=3s='%05d'%num#0代表用于分隔的数字,5代表输出总共占用5位print(s)#输出结果为00003,共占用5位注意:用\(0\)补位不会出现......
  • 学习笔记3
    关于知识点知识点归纳第十章10.1sh脚本sh脚本是一个包含sh语句的文本文件,命令解释程序sh要执行该语句。10.2sh脚本与C程序Shell脚本(sh脚本)和C程序是两种不同的编程语言和编程环境,它们有各自的特点和应用场景。Shell脚本(sh脚本):脚本语言:Shell脚本是一种脚本语言,通常......
  • 《动手学深度学习 Pytorch版》 7.7 稠密连接网络
    7.7.1从ResNet到DenseNetDenseNet可以视为ResNet的逻辑扩展。ResNet将函数展开为\(f(\boldsymbol{x})=x+g(\boldsymbol{x})\),即一个简单的线性项和一个复杂的非线性项。若将\(f\)拓展成超过两部分,则DenseNet便是其中一种方案。这即是DenseNet和ResNet的主要区......