1、read()和write()的使用
函数read()和write()、lseek()和close() 的基本使用与试验,实现文件的写入、读取、移位、关闭
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
int main()
{
int fd,size,len;
char *buf="hello ,this my test of this file";
char buf_r[100];
len=strlen(buf);
buf_r[100]='\0';
if((fd=open("hello.c",O_CREAT|O_TRUNC|O_RDWR,07777))<0){
perror("open :err");
exit(1);
}
else
printf("open file :hello.c %d\n",fd);
if((size=write(fd,buf,len))<0)
{perror("write :err"); exit(1);} //成功则显示成功,失败则显示失败
else
printf("write file: %s\n",buf);
lseek(fd,0,SEEK_SET);
if((size=read(fd,buf_r,len))<0)
{perror("read :err"); exit(1);} //成功则显示成功,失败则显示失败
else printf("read from the file is :%s\n",buf_r);
if((size=close(fd))<0)
{perror("read :err"); exit(1);} //成功则显示成功,失败则显示失败
else printf("close the file success\n");
return 0;
}
~
2、read、write与fread、fwrite的区别
1,fread是带缓冲的,read不带缓冲.
2,fopen是标准c里定义的,open是POSIX中定义的.
3,fread可以读一个结构.read在linux/unix中读二进制与普通文件没有区别.
4,fopen不能指定要创建文件的权限.open可以指定权限.
5,fopen返回指针,open返回文件描述符(整数).
6,linux/unix中任何设备都是文件,都可以用open,read.
如果文件的大小是8k。
你如果用read/write,且只分配了2k的缓存,则要将此文件读出需要做4次系统调用来实际从磁盘上读出。
如果你用fread/fwrite,则系统自动分配缓存,则读出此文件只要一次系统调用从磁盘上读出。
也就是用read/write要读4次磁盘,而用fread/fwrite则只要读1次磁盘。效率比read/write要高4倍。
如果程序对内存有限制,则用read/write比较好。
都用fread 和fwrite,它自动分配缓存,速度会很快,比自己来做要简单。如果要处理一些特殊的描述符,用read 和write,如套接口,管道之类的
系统调用write的效率取决于你buf的大小和你要写入的总数量,如果buf太小,你进入内核空间的次数大增,效率就低下。而fwrite会替你做缓存,减少了实际出现的系统调用,所以效率比较高。
如果只调用一次(可能吗?),这俩差不多,严格来说write要快一点点(因为实际上fwrite最后还是用了write做真正的写入文件系统工作),但是这其中的差别无所谓。
read/write 系统调用
read
函数从打开的设备或文件中读取数据。
#include <unistd.h> ssize_t read(int fd, void *buf, size_t count); 返回值:成功返回读取的字节数,出错返回-1并设置errno,如果在调read之前已到达文件末尾,则这次read返回0
参数count
是请求读取的字节数,读上来的数据保存在缓冲区buf
中,同时文件的当前读写位置向后移。注意这个读写位置和使用C标准I/O库时的读写位置有可能不同,这个读写位置是记在内核中的,而使用C标准I/O库时的读写位置是用户空间I/O缓冲区中的位置。
fread就是通过read来实现的,fread是C语言的库,而read是系统调用
但是差别在read每次读的数据是调用者要求的大小,比如调用要求读取10个字节数据,read就会读10个字节数据到数组中,而fread不一样,为了加快读的速度,fread每次都会读比要求更多的数据,然后放到缓冲区中,这样下次再读数据只需要到缓冲区中去取就可以了。
fread每次会读取一个缓冲区大小的数据,32位下一般是4096个字节,相当于调用了read(fd,buf,4096)
比如需要读取512个字节数据,分4次读取,调用read就是:
for(i=0; i<4; ++i)
read(fd,buf,128)
一共有4次系统调用
而fread一次就读取了4096字节放到缓冲区了,所以省事了
比如用fgetc
读一个字节,fgetc
有可能从内核中预读1024个字节到I/O缓冲区中,再返回第一个字节,这时该文件在内核中记录的读写位置是1024,而在FILE
结构体中记录的读写位置是1。注意返回值类型是ssize_t
,表示有符号的size_t
,这样既可以返回正的字节数、0(表示到达文件末尾)也可以返回负值-1(表示出错)。read
函数返回时,返回值说明了buf
中前多少个字节是刚读上来的。有些情况下,实际读到的字节数(返回值)会小于请求读的字节数count
,例如:
-
读常规文件时,在读到
count
个字节之前已到达文件末尾。例如,距文件末尾还有30个字节而请求读100个字节,则read
返回30,下次read
将返回0。 -
从终端设备读,通常以行为单位,读到换行符就返回了。
-
从网络读,根据不同的传输层协议和内核缓存机制,返回值可能小于请求的字节数,后面socket编程部分会详细讲解。