昨天我們學習了open和creat函數,今天我們繼續學習write、read和lseek函數,他們均定義在<unistd.h>。
1. read函數
1) 函數原型:
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
2) 函數功能:
read系統調用從文件描述符fd指向的文件中,讀取count個字節到buf中。
3) 參數說明:
fd:文件描述符
buf:保存讀入信息的緩存
count:要讀取的字節數
返回值:如果read成功,則返回讀到的字節數,如果已達到結尾,則返回0,出錯
返回-1
2. write函數
1) 函數原型:
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
2) 函數功能:
write系統調用將buf所指向的緩沖區的count個字節內容寫入fd指向的文件
3) 參數說明:
fd:要寫入的文件
buf:要寫入的信息所在的緩存
count:要寫入的字節數
返回值:如果write成功,則返回寫入的字節數,出錯返回-1
3. lseek函數
1) 函數原型:
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fildes, off_t offset, int whence);
2) 函數功能:
lseek系統調用用來移動讀寫指針的位置
3) 參數說明:
fd:要操作的文件
offset:相對whence移動的位移數,允許負值
whence:起始指針,它有三個取值
SEEK_SET 從文件開始處計算偏移量
SEEK_CUR 從文件指針的當前位置開始計算偏移量
SEEK_END 從文件結尾處開始計算偏移量
文件指針值等於當前指針值加上offset的值。
返回值:調用成功時范圍當前的讀寫位置,也就是距離文件開始處多少字節,若
有錯誤返回-1
4) 常見用法:
將文件讀寫指針移動到文件開頭:
lseek(int fildes, 0, SEEK_SET);
將文件讀寫指針移動到文件結尾:
lseek(int fildes, 0, SEEK_END);
獲取文件讀寫指針當前的位置
lseek(int fikdes, 0, SEEK_CUR);
注意:有些設備(或者說設備文件)不能使用lseek,linux系統不允許lseek()對tty設備進行操作,此項操作會使得lseek()范圍錯誤代碼ESPIPE
4.實例程序:
1)演示文件讀寫和文件指針的移動過程:
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <string.h> void my_error(const char* errstring, int line) { fprintf(stderr,"line:%d",line); perror(errstring); exit(1); } int my_read(int fd) { int len = 19,ret,i; char buf[128]; if((lseek(fd,0,SEEK_END)) == -1) { my_error("lseek",__LINE__); } if((len = lseek(fd,0,SEEK_CUR)) == -1) { my_error("lseek",__LINE__); } if((lseek(fd,0,SEEK_SET)) == -1) { my_error("lseek",__LINE__); } printf("文件長:%d\n",len); if((ret = read(fd,buf,len)) == -1) { my_error("read",__LINE__); } for(i=0;i<len;i++) { printf("%c",buf[i]); } printf("\n"); } int main() { int fd; char buf[128] = "my name is haohuai!"; umask(0000); if((fd = open("test.txt",O_RDWR | O_CREAT | O_TRUNC,0777)) == -1) { my_error("open",__LINE__); } else { printf("open success!\n"); } if(write(fd,buf,strlen(buf)) != strlen(buf)) { my_error("write",__LINE__); } else { printf("write success!\n"); } my_read(fd); return 0; }
注:1)其中__LINE__是預編譯器內置宏,表示當前行,類似的還有__TIME__、
__FUNCTION__ 、__FILE__等,表示時間、函數名、文件名。
2)read讀取文件之前一定要先將文件指針指向文件開始處,否則文件指針處
於文件結尾處。
運行結果:
[hb@localhost unixadvance]$ gcc -g -o testWRL testWRL.c
[hb@localhost unixadvance]$ ./testWRL
open success!
write success!
文件長:19
my name is haohuai!
2)將標准輸入復制到標准輸出
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <string.h> #define SIZE 1024 int main() { int n ; char buf[SIZE]; while((n = read(STDIN_FILENO,buf,SIZE)) > 0) { if(write(STDOUT_FILENO,buf,n) != n) { perror("write error"); } } if(n < 0) { perror("read error"); } return 0; }
注:STDIN_FILENO和STDOUT_FILENO分別是標准輸入和標准輸入的文件描述
符,一般是0和1,定義在<unistd.h>