首页 理论教育ARM嵌入式系统:Linux设备文件的读写

ARM嵌入式系统:Linux设备文件的读写

【摘要】:对一个打开的文件而言,最常用到的就是对文件的读写操作,在Linux系统中,提供了系统调用函数实现文件的读写操作。读取文件数据时,文件的当前读写位置会向后移。以下几种读取文件数据情况下,返回的字节数会小于count值。

对一个打开的文件而言,最常用到的就是对文件的读写操作,在Linux系统中,提供了系统调用函数实现文件的读写操作。

1.基于文件描述符的文件读写操作函数

(1)read()函数

read()函数从打开的文件(包括设备文件)中读取数据。该函数的定义形式如下:

#include<unistd.h>

ssize_t read(int fd,void∗buf,size_t count);

参数fd代表的是要进行读写的文件的描述符,参数buf代表的是读取的数据存放在buf指针所指向的缓冲区中,参数count代表的是读取的数据的字节数。读取文件数据时,文件的当前读写位置会向后移。需要注意的是:这个读写位置和使用C标准I/O库时的读写位置有可能不同,这个读写位置是记在内核中的,而使用C标准I/O库时的读写位置是用户空间I/O缓冲区中的位置。

函数调用成功,返回值为读取的字节数,否则返回值为-1,并设置适当的errno值。返回的字节数有时候会小于参数count值。以下几种读取文件数据情况下,返回的字节数会小于count值。如:

●读常规文件时,在读到count个字节之前已到达文件末尾。例如,距文件末尾还有30个字节而请求读100个字节,则read返回30,下次read将返回0;

●从终端设备上读时,通常以行为单位,读到换行符就返回;

●从网络上读时,根据不同的传输层协议和内核缓存机制,返回值可能小于请求的字节数。

(2)write()函数

write()函数向打开的设备或文件中写入数据,该函数的定义形式如下:

#include<unistd.h>

ssize_twrite(int fd,const void∗buf,size_t count);

参数fd代表的是想要写入数据的文件的文件描述符,参数buf指向写入文件的数据的缓冲区,参数count代表的是写入文件的数据的字节数。函数调用成功时,返回值为写入的字节数,否则返回值为-1,并设置适当的errno值。当向常规文件写入数据时,返回值会是字节数count,但是向终端设备或者网络中写入数据,返回值则不一定为写入的字节数。

2.基于数据流的文件读写操作函数

基于数据流的字符输入输出操作,实际上就是以字节为单位的读写操作,在C标准库中常用的读写字符的函数是fgetc()和fputc()。

(1)fgetc()函数

#include<stdio.h>

int fgetc(FILE∗stream);

参数stream为FILE结构体类型的指针,用于指向一个文件。使得该函数从指定文件中读取一个字节。函数fgetc()如果调用成功,则返回读到的字节;如果出错或者读到文件末尾时返回EOF。在程序中,偶尔会遇到getchar()函数,也是用于读取一个字节,但是它为从标准输入读一个字节。在程序中调用getchar()函数相当于调用fgetc(stdin)。

在使用fgetc()函数时需要注意以下两点。(www.chuimin.cn)

a)调用fgetc()函数时,指定的文件的打开方式必须是可读的。

b)函数fgetc()调用成功时,返回的是读到的字节,应该为unsigned char类型,但fgetc()函数原型中返回值类型是int,原因在于函数调用出错或读到文件末尾时fgetc()会返回EOF,即-1,保存在int型的返回值中是0xffffffff,如果读到字节0xff,由unsigned char型转换为int型是0x000000ff,只有规定返回值是int型才能把这两种情况区分开,如果规定返回值是unsigned char型,那么当返回值是0xff时无法区分到底是EOF还是字节0xff。

(2)fputc()函数

fputc()函数主要用于向指定的文件写一个字节,该函数的定义形式如下:

#include<stdio.h>

int fputc(int c,FILE∗stream);

该函数可以理解为将字节c写入到stream指针所指向的文件中。函数如果调用成功,则返回写入的字节,否则,返回EOF。在程序中,偶尔会遇到putchar()函数,也是用于向文件中写入一个字节,但是它为向标准输出写一个字节。在程序中调用putchar()函数相当于调用fputc(c,stdout)。

在使用fputc()函数时需要注意,调用fputc()函数时,指定文件的打开方式必须是可写的(包括追加)。

C标准库函数为字符串的输入输出提供了fputs()函数和fgets()函数。fputs()函数与fputc()函数类似,不同的是fputc()每次只向文件中写一个字符,而fputs()函数每次向文件中写入一个字符串。fgets()函数与fgetc()函数之间的关系是读取字符串与读取字符的关系。

(3)fgets()函数

函数fgets()的定义形式如下:

#include<stdio.h>

char∗fgets(char∗s,int size,FILE∗stream);

该函数实现了从参数stream所指向的文件中读取一串小于参数size所表示的字节数的字符串;然后将字符串存储到s所指向的缓冲区中。函数调用成功时返回内容为返回指向s所指向的缓冲区部分的指针;函数调用出错或者读到文件末尾时返回NULL。

在调用fgets()函数读取字符串时,以读取到‘\n’转义字符为结束,并在该行末尾添加一个‘\0’组成完整的字符串。在size字节范围内没有读到‘\n’结束符,则添加一个‘\0’,组成字符串存储到缓冲区中,文件中剩余的字符,等待下次调用fgets()函数时再读取。

对于fgets而言,‘\n’是一个特别的字符,作为结束符;而‘\0’并无任何特别之处,只用作普通字符读入。正因为‘\0’作为一个普通的字符,因此无法判断缓冲区中的‘\0’究竟是从文件读上来的字符还是由fgets()函数自动添加的结束符,所以fgets()函数只用于读文本文件而不提倡读二进制文件,并且文本文件中的所有字符不能有‘\0’。

(4)fputs()函数

函数fputs()的定义形式如下:

#include<stdio.h>

int fputs(const char∗s,FILE∗stream);

此函数用于实现向stream指针指向的文件写入s缓冲区中的字符串。函数如果调用成功返回值为一个非负整数,否则返回EOF。缓冲区s中保存的是以‘\0’结尾的字符串,fputs将该字符串写入文件stream,但并不写入结尾的‘\0’,且字符串中可以有‘\n’也可以没有‘\n’。