文件I/O读写操作
在上一篇文章中,我簡單講述了如何進行打開文件操作。而在這一篇文章中,我將會對打開的文件進行操作。
在進行文件讀寫操作之前,需要了解一個緩沖區(buff)的概念,緩沖區是在內存中預留指定大小的存儲空間用來對I/O的數據做臨時存儲,這部分預留的內存空間叫緩沖區。說白了就是內核把數據從文件中讀出來,沒地方放,只能在內存中開辟一塊臨時的空間去存放這個數據,直到這個數據再次被操作,這時候緩沖區中的數據就被拿走了。
下面是read函數和write函數,這兩個函數參數差不多,我把他們并在一起講下面先看函數定義:
是不是非常類似,在這里ssize_t是經過類型重定義的int型。
對于第一個參數fd,就是之前使用open函數打開的文件描述符,第二個參數就是最上面所說的緩沖區,我們需要自己定義一個緩沖區buff,一般都是
char buff[buffsize]=”\0”;在這里我把緩沖區buff給初始化了,這是為了防止緩沖區原本有亂碼。第三個參數是要讀字節的大小,一般來說我們直接填sizeof(buff)就好了。
他們的返回值都是已近操作的字節數(讀入的,讀出的),而錯誤都是返回-1。在這里我寫一段代碼用于計算文件大小。已知文件描述符fd,打開的文件中有字。
這樣子就完成了對一個文件中字節的計數。
下面我要講下lseek函數,即文件偏移量(current file offset),讀/寫操作是從當前文件偏移處開始的,在成功進行讀/寫操作后,文件偏移量增加,增加量是進行讀/寫的字節數。當文件剛剛打開時,文件偏移量被初始化為0。還記得之前的O_APPEND文件打開參數,則每次寫操作前,將文件位移量設置在文件的當前結尾處。
off_t也是類型重定義后int類型,fd是文件描述符,offset是對于基準點的偏移量,可正可負(向前移,向后移),whence是基準點,一般是宏定義,但是也可以寫成數字的形式。有以下三個基準點:
SEEK_SET:代表文件起始位置,數字表示為0
SEEK_CUR:代表文件當前的讀寫位置,數字表示為1
SEEK_END:代表文件結束位置,數字表示為2
最后,lseek函數返回值成功就是當前文件偏移量,失敗返回-1。
這里需要注意的是:
lseek函數不直接進行任何I/O操作,而是把數據記錄在內核中。而且該函數只對常規文件有效,對于管道,FIFO等無法進行操作。標準I/O中有個fseek與之類似。
最后再補充下文件偏移量實際中的應用:
文件位移量可以大于文件的當前長度,在這種情況下,對該文件的寫操作會延長文件,并形成空洞。
在UNIX/Linux文件操作中,文件位移量可以大于文件的當前長度,在這種情況下,對該文件的下一次寫將延長該文件,并在文件中構成一個空洞,這一點是允許的。位于文件中但沒有寫過的字節都被設為’\0’,用read讀取空洞部分讀出的數據是‘\0’。
空洞文件作用很大,例如迅雷下載文件,在未下載完成時就已經占據了全部文件大小的空間,這時候就是空洞文件。下載時如果沒有空洞文件,多線程下載時文件就都只能從一個地方寫入,這就不是多線程了。如果有了空洞文件,可以從不同的地址寫入,就完成了多線程的優勢任務。
Tips:可以使用ls -lh 和 du -sh 對比看空洞文件和正常文件的區別
總結
- 上一篇: 【CentOS】CentOS镜像文件各个
- 下一篇: 谷歌小恐龙修改无敌刷分