20.LINUX中的read函数

发布时间 2023-08-28 17:31:18作者: CodeMagicianT

20.LINUX中的read函数

1.read函数的函数原型

#include <unistd.h>
ssize_t read(int fd,void *buf,size_t count);

函数原型为:ssize_t read(int fd, void *buf, size_t count);其中,fd为文件描述符;buf表示读出数据缓冲区地址;count表示读出的字节数。返回值:若读取成功,则返回读到的字节数;若失败,返回-1;若已达到文件尾,则返回0。 这个函数的功能是从文件中读取指定数量的字节到缓冲区中。如果读取成功,函数会返回实际读取到的字节数;如果读取失败,函数会返回-1;如果已经到达文件末尾,函数会返回0。

2.read函数应用实例

编写简单的read函数程序,使用gcc编译器编译。read函数程序如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
	int fd;
	char buf[32] = { 0 };
	//char类型的buf,设置为32;给其做清零操作
	ssize_t ret;
	//read函数的返回值是ssize_t类型的,现在给其定义一个返回值命名为ret	
	fd = open("a.c", O_RDWR);
	//open"a.c文件",在之前open函数中已经创建了该文件

	if (fd < 0) 
	{
		printf("open is error\n");
		return -1;
	}

	printf("fd is %d\n", fd);
	ret = read(fd, buf, 32);
	//fd是通过open这个函数调用获得的;第二个参数是地址,写为buf;
	//第三个参数为要读取的字节数,这里选择写为32,与char buf[32]保持一致
	//最后打印返回值 为何打印ret?因为如果读取成功的话会返回读取的字节数
	//打印ret的值即可知道读取了多少字节 此处打开的是a.c 所以读取的时候会读取a.c里面的内容
	//在ubuntu界面给a.c文件写入“hello readfunction!”
	if (ret < 0) 
	{
		printf("read is error\n");
		return -2;
	}
	printf("buf is %s\n", buf);
	printf("ret is %ld\n", ret);
	close(fd);
	return 0;
} 

在ubuntu界面的运行结果命名为read为:

据char buf[32]={0}与ret=read(fd,buf,32);测试是否最大读取字节为32?
将a.c文件的内容写为:hello readfunction!hellohellohellohellohello
查看运行结果,如下:(最大读取字节数为32)

根据提供的代码和描述,以下是程序的行为:

  1. 当你使用 gcc read.c -o read 命令,你正在编译名为 read.c 的源代码文件,并将生成的可执行文件命名为 read
  2. 当你运行 ./read,你正在执行这个可执行文件。

在你的描述中,当你执行程序后,输出为:

fd is 3
buf is hello readfunction!

现在,我来解释这些输出:

  • fd is 3: 在UNIX和Linux系统中,当你打开一个文件,操作系统会为该文件提供一个文件描述符。文件描述符是一个非负整数。通常,描述符0、1和2分别代表标准输入、标准输出和标准错误输出。因此,当你首次在程序中打开一个文件,它通常会得到文件描述符3,这就解释了为什么输出是 "fd is 3"。

  • buf is hello readfunction!: 这是你从 a.c 文件中读取的内容。你的代码从该文件读取了最多32个字节的数据,然后将这些数据存储在 buf 中。因为 a.c 的内容是 "hello readfunction!",所以你的代码读取并显示了这个内容。


这段代码是一个简单的C程序,用于打开名为“a.c”的文件,从中读取最多32个字节的数据,然后显示读取到的数据和实际读取的字节数。接下来我会逐行解释代码的作用:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

上述头文件包含了程序中使用到的各种函数和数据类型的声明。

int main(int argc, char* argv[])
{
	int fd;
	char buf[32] = { 0 };

在主函数中,定义了文件描述符 fd 用于存储文件的引用,定义了一个32字节的字符数组 buf 用于存储从文件中读取的数据。

	ssize_t ret;

定义一个 ssize_t 类型的变量 ret,用于存储 read 函数的返回值。

	fd = open("a.c", O_RDWR);

尝试以读写模式打开名为 "a.c" 的文件。成功打开的话,open 函数返回一个非负的文件描述符;否则返回-1。

	if (fd < 0) 
	{
		printf("open is error\n");
		return -1;
	}

检查文件是否成功打开。如果 fd 小于0,表示打开文件出错,并输出错误消息。

	printf("fd is %d\n", fd);

打印文件描述符的值。

	ret = read(fd, buf, 32);

从文件描述符 fd 指向的文件中读取最多32个字节的数据,并将读取的数据存放到 buf 中。

	if (ret < 0) 
	{
		printf("read is error\n");
		return -2;
	}

检查 read 函数是否成功。如果 ret 小于0,表示读取数据时出错,并输出错误消息。

	printf("buf is %s\n", buf);

打印从文件中读取的数据。请注意,假设读取的数据是一个有效的字符串。

	printf("ret is %ld\n", ret);

打印实际从文件中读取的字节数。

	close(fd);

关闭文件描述符,释放与之相关联的资源。

	return 0;
}

程序成功执行后返回0。

总的来说,这段代码展示了如何在C语言中使用 open, read, 和 close 函数进行文件操作。

3.说明

在man手册对于read函数的说明中提到:除去读取失败的情况,如果读取到文件的末尾,此时再读取时,返回值也会是0。
做一下测试,在刚才的C代码读取完成之后再加入一段读取操作。(将a.c文件的内容再回去“hello readfunction!”)

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
	int fd;
	char buf[32] = { 0 };
	//char类型的buf,设置为32;给其做清零操作
	ssize_t ret;
	//read函数的返回值是ssize_t类型的,现在给其定义一个返回值命名为ret	
	fd = open("a.c", O_RDWR);
	//open"a.c文件",在之前open函数中已经创建了该文件

	if (fd < 0) 
	{
		printf("open is error\n");
		return -1;
	}

	printf("fd is %d\n", fd);
	ret = read(fd, buf, 32);
	//fd是通过open这个函数调用获得的;第二个参数是地址,写为buf;
	//第三个参数为要读取的字节数,这里选择写为32,与char buf[32]保持一致
	//最后打印返回值 为何打印ret?因为如果读取成功的话会返回读取的字节数
	//打印ret的值即可知道读取了多少字节 此处打开的是a.c 所以读取的时候会读取a.c里面的内容
	//在ubuntu界面给a.c文件写入“hello readfunction!”
	if (ret < 0)
	{
		printf("read is error\n");
		return -2;
	}
	printf("buf is %s\n", buf);
	printf("ret is %ld\n", ret);

	ret = read(fd, buf, 32);
	if (ret < 0) 
	{
		printf("read is error\n");
		return -2;
	}
	printf("buf is %s\n", buf);
	printf("ret is %ld\n", ret);//二次执行read读取

	close(fd);
	return 0;
}

在ubuntu界面的运行结果命名为read1,结果如下:

4.总结

在此次编写的代码中,read函数如果调用成功的话,它返回的是实际读到的字节数;它如果返回的是0,表示它已经读到了文件的末尾;如果返回的是-1,表示读取出错。

参考资料:

嵌入式学习之linux系统编程---4 文件IO之read函数