1.文件描述符 文件描述符(file descriptor)通常是一个小的非负整数,内核用以 标识一个特定进程正在访问的文件。当内核打开一个现有文件或创建一 个新文件时,它都返回一个文件描述符。在读、写文件时,可以使用这 个文件描述符。

2.标准输入、标准输出和标准错误 按惯例,每当运行一个新程序时,所有的 shell 都为其打开 3 个文 件描述符,即标准输入(standard input)、标准输出(standard output) 以及标准错误(standard error)。如果不做特殊处理,例如就像简单的 命令ls,则这3个描述符都链接向终端。大多数shell都提供一种方法,使 其中任何一个或所有这3个描述符都能重新定向到某个文件,例如: ls > file.list 执行ls命令,其标准输出重新定向到名为file.list的文件。

3.不带缓冲的I/O 函数open、read、write、lseek以及close提供了不带缓冲的I/O。这些 函数都使用文件描述符。

1、read()

函数定义:ssize_t read(int fd, void * buf, size_t count);

函数说明:read()会把参数fd所指的文件传送count 个字节到buf 指针所指的内存中。

返回值:返回值为实际读取到的字节数, 如果返回0, 表示已到达文件尾或是无可读取的数据。若参数count 为0, 则read()不会有作用并返回0。另外,以下情况返回值小于count:
(1)读常规文件时,在读到count个字节之前已到达文件末尾。例如,距文件末尾还有50个字节而请求读100个字节,则read返回50,下次read将返回0。
(2)对于网络套接字接口,返回值可能小于count,但这不是错误,详细解释参考这篇文章https://blog.csdn.net/hhhlizhao/article/details/73912578
注意:read时fd中的数据如果小于要读取的数据,就会引起阻塞。(关于read的阻塞情况网上有朋友有不同意见,笔者查阅资料后作如下补充。)以下情况read不会引起阻塞:

(1)常规文件不会阻塞,不管读到多少数据都会返回;

(2)从终端读不一定阻塞:如果从终端输入的数据没有换行符,调用read读终端设备会阻塞,其他情况下不阻塞;

(3)从网络设备读不一定阻塞:如果网络上没有接收到数据包,调用read会阻塞,除此之外读取的数值小于count也可能不阻塞,原因见上面链接。

由于笔者水平有限,如果文中有谬误之处还恳请诸位指出,以免误导大家。

2、write()
函数定义:ssize_t write (int fd, const void * buf, size_t count);

函数说明:write()会把参数buf所指的内存写入count个字节到所指的文件fd内。

返回值:如果顺利write()会返回实际写入的字节数。当有错误发生时则返回-1,错误代码存入errno中。

附加说明:

(1)write()函数返回值一般无0,只有当如下情况发生时才会返回0:write(fd, buf, count)中第三参数为0,此时write()什么也不做,只返回0。

(2)write()函数从buf写数据到fd中时,若buf中数据无法一次性读完,那么第二次读buf中数据时,其读位置指针(也就是第二个参数buf)不会自动移动,需要程序员来控制,而不是简单的将buf首地址填入第二参数即可。如可按如下格式实现读位置移动:write(fp, p1+len, (strlen(p1)-len))。 这样write第二次循环时便会从p1+len处写数据到fp, 之后的也一样。由此类推,直至(strlen(p1)-len)变为0。

(3)在write一次可以写的最大数据范围内(貌似是BUFSIZ ,8192),第三参数count大小最好为buf中数据的大小,以免出现错误。(经过笔者再次试验,write一次能够写入的并不只有8192这么多,笔者尝试一次写入81920000,结果也是可以,看来其一次最大写入数据并不是8192,但内核中确实有BUFSIZ这个参数,具体指什么还有待研究)

我们可以写一个简单的文件读写程序,实现从标准输入到标准输出echo(复读机)

#include "../all.h"
#include <unistd.h>
#define BUFFSIZE 4096int main(int argc, char* argv[]) {int n = 0;char buf[BUFFSIZE];printf("This is a simple read/write test\n");while((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0) {if(write(STDOUT_FILENO, buf, n)!=n) {printf("write error\n");}}if(n < 0) {printf("read error\n");}return 0;
}
echo复读机

还可以打开文件,输出到标准输出 实现cat

#include "../all.h"
#include <fcntl.h>
#include <unistd.h>
#define BUFFSIZE 4096
int main(int argc, char* argv[]) {printf("this is a simple cat, will show the file\n");if(argc  < 2) {printf("argument not enough , at least 2\n");exit(-1);}char buf[BUFFSIZE];memset(buf,0,BUFFSIZE);int n =0;int fd = open(argv[1], O_RDWR|O_CREAT);while(true) {int len = 0;while((n= read(fd, buf,BUFFSIZE)) > 0) {if(write(STDOUT_FILENO,buf + len,n) !=n) {printf("write error\n");exit(-1);} len+=n;}break;}return 0;
}
简单的cat

头文件<unistd.h>(apue.h中包含了此头文件)及两个常量 STDIN_FILENO和STDOUT_FILENO是POSIX标准的一部分(下一章 将对此做更多的说明)。头文件<unistd.h>包含了很多UNIX系统服务的 函数原型。

两个常量STDIN_FILENO和STDOUT_FILENO定义在<unistd.h>头 文件中,它们指定了标准输入和标准输出的文件描述符。在POSIX标准 中,它们的值分别是0和1,但是考虑到可读性,我们将使用这些名字来 表示这些常量。

将详细讨论BUFFSIZE常量,说明它的各种不同值将如何影响 程序的效率。但是不管该常量的值如何,此程序总能复制任一UNIX普 通文件。

4.标准I/O
read函数返回读取的字节数,此值用作要写的字节数。当到达输入 文件的尾端时,read返回0,程序停止执行。如果发生了一个读错误, read返回−1。出错时大多数系统函数返回−1。 标准I/O函数为那些不带缓冲的I/O函数提供了一个带缓冲的接 口。使用标准I/O函数无需担心如何选取最佳的缓冲区大小。例如,fgets函数读取一个完整的 行,而read函数读取指定字节数。

我们最熟悉的标准I/O函数是printf。在调用printf的程序中,总是包 含<stdio.h>(在本书中,该头文件包含在apue.h中),该头文件包括了 所有标准I/O函数的原型。

深入了解C read/write函数和cat命令实现相关推荐

  1. R语言print函数和cat函数打印数据对象实战

    R语言print函数和cat函数打印数据对象实战 目录 R语言print函数和cat函数打印数据对象实战 #基本语法

  2. R语言打印函数,print函数和cat函数实战

    R语言打印函数,print函数和cat函数实战 目录 R语言print函数和cat函数实战 #基本语法 # print()函数和cat()函数对比

  3. Linux cat 命令用法

    cat主要有三大功能: 1.一次显示整个文件. $ cat filename 2.从键盘创建一个文件. $ cat > filename 只能创建新文件,不能编辑已有文件. 3.将几个文件合并为 ...

  4. 用C语言实现一个cat命令

    用C语言实现一个简单的cat命令 今天老师又留了一个作业, ## cat作业> 参照系统自带的`cat`实现自己的`cat`命令.1. 实现`-b`选项:输出文件,对空行不编号 2. 实现`-n ...

  5. Linux system函数的执行命令并获取状态

    在linux中,可以通过调用system函数执行linux命令,但是如何获取执行命令的结果状态呢,也就是是否执行成功. #include <stdio.h> #include <st ...

  6. linux cat 查看文件内容 不带#号的,Linux下如何不用cat命令读取文件内容

    本文最后更新于2018年1月28日,已超过 1 年没有更新,如果文章内容失效,还请反馈给我,谢谢! =Start= 缘由: 在微信群里看到的一个讨论,觉得挺有启发意义的,所以在此整理一下,方便以后学习 ...

  7. 每天一个linux命令(10):cat 命令

    cat命令的用途是连接文件或标准输入并打印.这个命令常用来显示文件内容,或者将几个文件连接起来显示,或者从标准输入读取内容并显示,它常与重定向符号配合使用. 1.命令格式: cat [选项] [文件] ...

  8. 别再用ls、cat命令了,这有一套全新升级版,简洁快速还易上手

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 明敏 发自 凹非寺 量子位 报道 | 公众号 QbitAI 最近,一 ...

  9. Linux 文件系统常用命令:cat命令

    2019独角兽企业重金招聘Python工程师标准>>> 作者:马哥教育 来源:http://www.magedu.com/73449.html 1.cat命令的定义 Cat:conc ...

最新文章

  1. 带无线网卡的电脑开启热点
  2. linux history(命令历史)
  3. 高并发下的redis击穿,你需要了解下布隆过滤器
  4. python 哈希表_哈希表哪家强?编程语言找你来帮忙!
  5. nestjs CRUD
  6. NIO : selector、channel、buffer的实例
  7. 成熟的夜间模式解决方案
  8. 南京工业大学python考试期末题库_大学慕课2020用Python玩转数据期末考试大全答案...
  9. java 对象池 博客_Java对象池技术的原理及其实现的小结
  10. Win11手机应用大改!全新界面来袭
  11. 跋山涉水——深入 Redis 字典遍历
  12. 使用base64 对Json 的返回数据进行优化
  13. Uploading SSH public key ... failed!
  14. 重拾C++之虚函数和虚基类以及抽象类
  15. 2013小企业会计新准则下会计科目的变化
  16. 环境科学概论知识点总结
  17. 学生专用计算机怎么打,电脑使用word快速打出学生座位表的方法
  18. 【Linux】FirefoxBrowser 火狐浏览器安装 FlashPlayer 插件
  19. 【office 2007~office 2019】Excel日期选择控件插件安装
  20. 连续型随机变量与离散型随机变量

热门文章

  1. 保留状态的秘密 - 深入了解Java备忘录模式(Memento Pattern)
  2. Linux应用程序解决方案
  3. Hive SQL 迁移 Flink SQL 在快手的实践
  4. Wordpress ThickBox 特效修改:添加“查看原图”
  5. 北京筑龙:采购供应链平台构建能源企业 数智信创供应链的必经之路
  6. Go语言 时间相关的转化:纳秒转 毫秒 转 英文时间格式 中文格式化
  7. 自然语言处理(NLP)-第三方库(工具包):Annoy 【向量最邻近检索工具】
  8. 博客日记2022.1.6
  9. Oracle EBS Interface/API(31) -PR最终关闭API
  10. NC63 前台新增按钮