在 c 编程领域,有效管理输入、输出和内存是基础。为了帮助您掌握这些关键概念,您将在 get_next_line 项目中编写一个使用文件描述符逐行读取文件的函数。每次调用该函数都会从文件中读取下一行,从而允许您一次一行处理整个文件内容。
了解系统中的文件描述符和 i/o
什么是文件描述符?
文件描述符是一个非负整数,唯一标识系统中打开的文件。当程序打开文件时,操作系统返回一个文件描述符,可用于在后续操作(例如读取、写入或关闭文件)中引用该文件。文件描述符是操作系统用来管理各种 i/o 资源的抽象,包括文件、套接字和管道。
进程 a 中的 0、1 和 2(标准输入、标准输出和标准错误)与进程 b 中的文件描述符是独立且分开的。这种隔离确保一个进程中的文件操作不会干扰其他进程中的文件操作。另一个。
文件描述符表
每个文件描述符都与一个文件描述符表条目相关联,其中包含有关文件的基本信息。这包括文件路径、访问权限和当前偏移量,该偏移量跟踪文件中读/写操作的位置。这种结构允许操作系统有效地管理多个打开的文件并确保正确的访问和数据操作。
请注意,文件描述符 0、1 和 2 是操作系统为标准流保留的。文件描述符 0 用于标准输入 (stdin),通常表示来自键盘的输入。文件描述符 1 用于标准输出 (stdout),表示输出到屏幕或终端。文件描述符 2 用于标准错误 (stderr),它也表示到屏幕或终端的输出,但专门用于错误消息。这些保留的文件描述符确保可以跨不同的程序和环境一致地管理基本输入和输出操作。 open 函数返回的任何文件描述符都将为 3 或更高,确保它不会与这些标准流冲突。
如何打开文件
例子
<p>'#include <fcntl.h>'<br> '#include <unistd.h>'</unistd.h></fcntl.h></p> <p>int fd = open("example.txt", o_rdonly);<br> if (fd == -1) {<br> perror("error opening file");<br> return 1;<br> }</p>
代码分解
使用 open 函数获取以整数表示的文件描述符,该函数采用两个参数:文件名(或路径)和确定文件访问权限的标志。例如,要读取文件的内容,我们使用 o_rdonly 标志(只读)。为了读取和写入,我们使用 o_rdwr 标志。虽然有许多可用标志,但我们将仅在该项目中使用 o_rdonly。 open函数返回一个非负整数,如果操作成功则为文件描述符;否则,它返回 -1 以指示错误(您没有访问 example.txt 的权限)。注意,open函数在unistd.h库中,权限标志在fcntl.h中定义。
从文件描述符读取
例子
<p>'#include <fcntl.h>'<br> '#include <unistd.h>'<br> '#include <stdio.h>'<br> '#define BUFFER_SIZE 4'</stdio.h></unistd.h></fcntl.h></p> <p>int fd = open("example.txt", O_RDONLY);<br> if (fd == -1) {<br> perror("Error opening file");<br> return 1;<br> }<br> char buffer[BUFFER_SIZE];<br> read(fd, buffer, sizeof(buffer)-1);<br> printf("1st call : %sn", buffer);<br> // prints the first 3 bytes<br> read(fd, buffer, sizeof(buffer)-1);<br> printf("2nd call : %sn", buffer);<br> read(fd, buffer, sizeof(buffer)-1);<br> printf("3rd call : %sn", buffer);<br> read(fd, buffer, sizeof(buffer)-1);<br> printf("4th call : %sn", buffer);<br> read(fd, buffer, sizeof(buffer)-1);<br> printf("5th call : %sn", buffer);</p>
故障
代码结果
第一个电话:hel
第二次通话:lo
第三通电话:wor
第四个电话:ld
第五次通话:(null)
unistd.h 库提供的 read 函数用于从文件描述符读取数据。它需要三个参数:文件描述符、存储读取数据的缓冲区以及要从文件中读取的字节数,read 函数返回从文件中读取的字节数。
在文件描述符表中,有一个属性叫做offset。偏移量跟踪文件中的当前位置。每次调用 read 函数时,它都会从当前偏移量开始读取数据,然后将偏移量前进所读取的字节数。这可确保后续读取从上次读取停止的位置继续。
在我们的示例中:
- 第一次调用 read 会从文件的开头(偏移量 0)开始读取文件的前 3 个字节并将它们存储在缓冲区中。然后偏移量更新为 3。
第二次调用 read 读取从更新的偏移量 (3) 开始的接下来的 3 个字节,然后将偏移量更新为 6。
等等...第 5 次调用读取缓冲区将为空,并且 read 返回 0 表示文件结束。
此过程将持续进行,直到从文件中读取所有数据或发生错误。每次读取后缓冲区都以 null 终止,以确保它可以作为字符串打印。
问题
char *get_next_line(int fd) 将文件的文件描述符作为参数,并为每次调用返回一行。如果到达文件末尾,则返回 null。
参数
- fd:要读取的文件的文件描述符。
- buffer_size:用于从文件读取块的缓冲区的大小。 你的程序应该没有泄漏。
解决方案 :
https://github.com/its-joetheking/get_next_line
以上就是获取下一行学习如何处理文件描述符和系统 I/O 的项目的详细内容,更多请关注php中文网其它相关文章!