c 学习笔记之 c IO标准库函数

本文深入探讨了Linux下的IO操作原理,介绍了文件系统的基本概念,包括文本文件与二进制文件的区别,以及设备文件的分类。此外,文章还详细解释了Linux系统调用如open、close、read、write等,并对带有缓冲的文件操作进行了封装说明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 一直以来对c的IO函数一知半解,今天终于仔细研究了一下有些醍醐灌顶的感觉。

 

首先是对文件的理解。linux下,一切皆为文件,liunx就是一个大文件系统。

我们常见的文件一般是,文本文件和二进制文件。

文本文件主要是记录一些可读字符,这些字符是以字节为单位组织起来,可以是ascii码 utf8,iso gbk等编码形式。

主要可以是文件,源码文件等等。

二进制文件 则不是一些可读的文件,如系统中可执行文件,库文件,目标文件等。每个字节中的二进制位可能代表,地址,数据,指令。等等

设备文件,每个设备也被linux 抽象成一个文件,这些设备文件没有size这样的属性,因为它连接外部设备,将数据输出到设备外,或是度入到内存中。

Linux 中的设备有2种类型:字符设备(无缓冲且只能顺序存取)、块设备(有缓冲且可以随机存取)。每个字符设备和块设备都必须有主、次设备号,主设备号相同的设备是同类设备(使用同一个驱动程序)。这些设备中,有些设备是对实际存在的物理硬件的抽象,而有些设备则是内核自身提供的功能(不依赖于特定的物理硬件,又称为"虚拟设备")。每个设备在 /dev 目录下都有一个对应的文件(节点)。可以通过 cat /proc/devices 命令查看当前已经加载的设备驱动程序的主设备号。内核能够识别的所有设备都记录在原码树下的 Documentation/devices.txt 文件中。在 /dev 目录下除了字符设备和块设备节点之外还通常还会存在:FIFO管道、Socket、软/硬连接、目录。这些东西没有主/次设备号。

详情参考 http://lamp.linux.gov.cn/Linux/device_files.html

 

因为文件基本构成都是一样所以可以以读字节方式读取整个文件。

 

linux 有几个IO 的系统调用 都是无缓冲的,他们适用任何IO操作 open close read write lseek

频繁访问系统内核,效率低

 

对其封装成带有缓冲的文件操作IO

 

FILE 文件结构体 包括一个文件描述符,和文件缓冲区地址,以及一个指针

 

FILE * fd = fopen (const * str,const * op)//错误返回 NULL

r, w ,a , r+, w+ ,a+

 

fclose(fd); //成功返回0 错误返回EOF,并设置 errno

 

stdin stdout stderr 分别表示, 标准输入,标准输出,和标准错误输出,是与用户交互操作的一些

 

程序出现错误的时候 会设置errno

输出errno 同时 输出对应的错误说明 可以使用 perror(自定义错误日) 函数 和 strerror(errno)

 

 

fgetchar 与 fputchar (getchar 与putchar 是 标准输入输出的版本)

fgetchar 是行缓冲函数

每次读入一个字符到缓冲区,当遇到换行时,清空缓冲区。

当读到文件位的时候 返回EOF -1 0xFFFFFFFF

返回值是 int 要区分 EOF 和 0xFF ,如果不是EOF 转化为unsigned char 返回

 

getchar有一个int型的返回值.当程序调用getchar时.程序就等着用户按键.用户输入的字符被存放在键盘缓冲区中.直到用户按回车为止(回车字符也放在缓冲区中).当用户键入回车之后,getchar才开始从stdin流中每次读入一个字符.getchar函数的返回值是用户输入的第一个字符的ASCII码,如出错返回-1,且将用户输入的字符回显到屏幕.如用户在按回车之前输入了不止一个字符,其他字符会保留在键盘缓存区中,等待后续getchar调用读取.也就是说,后续的getchar调用不会等待用户按键,而直接读取缓冲区中的字符,直到缓冲区中的字符读完为后,才等待用户按键.

getch与getchar基本功能相同,差别是getch直接从键盘获取键值,不等待用户按回车,只要用户按一个键,getch就立刻返回, getch返回值是用户输入的ASCII码,出错返回-1.输入的字符不会回显在屏幕上.getch函数常用于程序调试中,在调试时,在关键位置显示有关的结果以待查看,然后用getch函数暂停程序运行,当按任意键后程序继续运行.

 

文件结束可以使用ctrl + d 也可以使用linux heredoc 《end 《end

 

有三个对文件位置修改的文件

rewind 对文件指针回到文件头

fseek(File * fd, int offset, int wherence)// offset 可正可负 如果超出了文件范围,在读写则添零

ftell(File * fd)

 

可以对文件分块,多线程传输

 

SEEK_SET
从文件开头移动offset个字节
SEEK_CUR
从当前位置移动offset个字节
SEEK_END
从文件末尾移动offset个字节

 

fgets (char * buf, int size, FILE *fd) //从fd 读取长度为size-1长的的字符串 并在读取的数据后加入/0作为字符串结束符

                                                             如果遇到换行,则返回

                                                             如果所读行的大小大于 缓冲区大小则截断 字符串

 

 

对于fgets来说,'/n'是一个特别的字符,而'/0'并无任何特别之处,如果读到'/0'就当作普通字符读入。如果文件中存在'/0'字符(或者说0x00字节),调用fgets之后就无法判断缓冲区中的'/0'究竟是从文件读上来的字符还是由fgets自动添加的结束符,所以fgets只适合读文本文件而不适合读二进制文件,并且文本文件中的所有字符都应该是可见字符,不能有'/0'。

如果文件结束则返回NULL

fread 和fwrite 对记录的读取, 可以读取一个结构体或是一个数组

 

太晚了先写这么多

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值