Linux(C/C++)下的文件操作open、fopen與freopen

Linux(C/C++)下的文件操作open、fopen與freopen

open是linux下的底層系統調用函數,fopen與freopen c/c++下的標準I/O庫函數,帶輸入/輸出緩沖。

linxu下的fopen是open的封裝函數,fopen最終還是要調用底層的系統調用open。

所以在linux下如果需要對設備進行明確的控制,那最好使用底層系統調用(open),

open對應的文件操作有:close, read, write,ioctl 等。

fopen對應的文件操作有:fclose, fread, fwrite, freopen, fseek, ftell, rewind等。

freopen用于重定向輸入輸出流的函數,該函數可以在不改變代碼原貌的情況下改變輸入輸出環境,但使用時應當保證流是可靠的。詳細見第3部分。

-------------------------------------------------------------------------------------------------------------------

open和fopen的區別:

1,fread是帶緩沖的,read不帶緩沖.

2,fopen是標準c里定義的,open是POSIX中定義的.

3,fread可以讀一個結構.read在linux/unix中讀二進制與普通文件沒有區別.

4,fopen不能指定要創建文件的權限.open可以指定權限.

5,fopen返回文件指針,open返回文件描述符(整數).

6,linux/unix中任何設備都是文件,都可以用open,read.

-------------------------------------------------------------------------------------------------------------------

1、open系統調用(linux)

需要包含頭文件:#include

#include

#include

函數原型:int open( const char * pathname, int oflags);

int open( const char * pathname,int oflags, mode_t mode);

mode僅當創建新文件時才使用,用于指定文件的訪問權限。

pathname是待打開/創建文件的路徑名;

oflags用于指定文件的打開/創建模式,這個參數可由以下常量(定義于 fcntl.h)通過邏輯或構成。

O_RDONLY ? ? ? 只讀模式

O_WRONLY ? ? ?只寫模式

O_RDWR ? ? ? ? ?讀寫模式

以上三者是互斥的,即不可以同時使用。

打開/創建文件時,至少得使用上述三個常量中的一個。以下常量是選用的:

O_APPEND ? ? ? ? 每次寫操作都寫入文件的末尾

O_CREAT ? ? ? ? ? ?如果指定文件不存在,則創建這個文件

O_EXCL ? ? ? ? ? ? ? 如果要創建的文件已存在,則返回 -1,并且修改 errno 的值

O_TRUNC ? ? ? ? ? 如果文件存在,并且以只寫/讀寫方式打開,則清空文件全部內容

O_NOCTTY ? ? ? ? 如果路徑名指向終端設備,不要把這個設備用作控制終端。

O_NONBLOCK ? 如果路徑名指向 FIFO/塊文件/字符文件,則把文件的打開和后繼 I/O設置為非阻塞模式(nonblocking mode)。

//以下用于同步輸入輸出

O_DSYNC ? ? ? ? ?等待物理 I/O 結束后再 write。在不影響讀取新寫入的數據的前提下,不等待文件屬性更新。

O_RSYNC ? ? ? ? ?read 等待所有寫入同一區域的寫操作完成后再進行

O_SYNC ? ? ? ? ? ?等待物理 I/O 結束后再 write,包括更新文件屬性的 I/O

當你使用帶有O_CREAT標志的open調用來創建文件時,你必須使用有3個參數格式的open調用。第三個參數mode是幾個標志按位或后得到的,

這些標志在頭文件sys/stat.h中定義,如下所示:

S_IRUSR: ? ?讀權限,文件屬主

S_IWUSR: ? 寫權限,文件屬主

S_IXUSR: ? ?執行權限,文件屬主

S_IRGRP: ? ?讀權限,文件所屬組

S_IWGRP: ? 寫權限,文件所屬組

S_IXGRP: ? ?執行權限,文件所屬組

S_IROTH: ? 讀權限,其它用戶

S_IWOTH: ?寫權限,其它用戶

S_IXOTH: ? 執行權限,其它用戶

返回值:成功則返回文件描述符,否則返回 -1。??返回文件描述符(整型變量0~255)。由open 返回的文件描述符一定是該進程尚未使用的最小描述符。只要有一個權限被禁止則返回-1。

錯誤代碼:(均已E開頭,將其去掉就是有關于錯誤的方面的單詞或單詞的縮寫)

EEXIST 參數pathname 所指的文件已存在,卻使用了O_CREAT和O_EXCL旗標。

EACCESS 參數pathname所指的文件不符合所要求測試的權限。

EROFS 欲測試寫入權限的文件存在于只讀文件系統內。

EFAULT 參數pathname指針超出可存取內存空間。

EINVAL 參數mode 不正確。ENAMETOOLONG 參數pathname太長。

ENOTDIR 參數pathname不是目錄。

ENOMEM 核心內存不足。

ELOOP 參數pathname有過多符號連接問題。

EIO I/O 存取錯誤。

-------------------------------------------------------------------------------------------------------------------

ssize_t write(int fd, const void *buf, size_t count);

參數

fd:要進行寫操作的文件描述詞。

buf:需要輸出的緩沖區

count:最大輸出字節計數

返回值:成功返回寫入的字節數,出錯返回-1并設置errno

-----------------------------------------------.--------------------------------------------------------------------

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

參數

buf:需要讀取的緩沖區

count:最大讀取字節計數

返回值:成功返回讀取的字節數,出錯返回-1并設置errno,如果在調read之前已到達文件末尾,則這次read返回0

-------------------------------------------------------------------------------------------------------------------

2、fopen庫函數

頭文件

函數原型:FILE * fopen(const char * path, const char * mode);

path字符串包含欲打開的文件路徑及文件名,參數mode字符串則代表著流形態。

mode有下列幾種形態字符串:

"r"或"rb" ? ? ? ?以只讀方式打開文件,該文件必須存在。

"w"或"wb" ? ? 以寫方式打開文件,并把文件長度截短為零。

"a"或"ab" ? ? ?以寫方式打開文件,新內容追加在文件尾。

"r+"或"rb+"或"r+b" ? ? ? 以更新方式打開(讀和寫)

"w+"或"wb+"或"w+b" ? 以更新方式打開,并把文件長度截短為零。

"a+"或"ab+"或"a+b" ? ? 以更新方式打開,新內容追加在文件尾。

字母b表示文件時一個二進制文件而不是文本文件。(linux下不區分二進制文件和文本文件)

返回值:文件順利打開后,指向該流的文件指針就會被返回。如果文件打開失敗則返回NULL,并把錯誤代碼存在errno 中。

-------------------------------------------------------------------------------------------------------------------

fread是一個函數。從一個文件流中讀數據,最多讀取count個元素,每個元素size字節,如果調用成功返回實際讀取到的元素個數,如果不成功或讀到文件末尾返回 0。

函數原型:size_t fread ( void *buffer, size_t size, size_t count, FILE *stream) ;

參 數:

buffer:用于接收數據的內存地址

size:要讀寫的字節數,單位是字節

count:要進行讀寫多少個size字節的數據項,每個元素是size字節.

stream:輸入流

返回值:實際讀取的元素個數.如果返回值與count不相同,則可能文件結尾或發生錯誤,從ferror和feof獲取錯誤信息或檢測是否到達文件結尾.

-------------------------------------------------------------------------------------------------------------------

fwrite:向文件寫入一個數據塊

函數原型:size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream);

參數:

buffer:是一個指針,對fwrite來說,是要獲取數據的地址;

size:要寫入內容的單字節數;

count:要進行寫入size字節的數據項的個數;

stream:目標文件指針;

返回值:返回實際寫入的數據塊數目

-------------------------------------------------------------------------------------------------------------------

fflush:把文件流里的所有為寫出數據立刻寫出。

函數原型:int fflush(FILE *stream);

-------------------------------------------------------------------------------------------------------------------

fseek:是lseek系統調用對應的文件流函數。它在文件流里為下一次讀寫操作指定位置。

函數原型:int fseek(FILE *stream, long offset, int fromwhere);

參數stream為文件指針

參數offset為偏移量,正數表示正向偏移,負數表示負向偏移

參數fromwhere設定從文件的哪里開始偏移,可能取值為:SEEK_CUR、 SEEK_END 或 SEEK_SET

SEEK_SET: 文件開頭

SEEK_CUR: 當前位置

SEEK_END: 文件結尾

其中SEEK_SET,SEEK_CUR和SEEK_END依次為0,1和2.

返回值:如果執行成功,stream將指向以fromwhere為基準,偏移offset(指針偏移量)個字節的位置,函數返回0。如果執行失敗(比如offset超過文件自身大小),則不改變stream指向的位置,函數返回一個非0值。

-------------------------------------------------------------------------------------------------------------------

以下為linux下一個打開文件并顯示文件內容的程序:

#include

#include

#include

#include

#include

#include

#include

char * FILE_NAME = "/home/hzg/uart/download.bin";

unsigned char file_buffer[20];

int main()

{

FILE * file_fd;

int read_len, i;

file_fd = fopen(FILE_NAME,"rb");

if(file_fd == NULL)

{

perror("errno");

}

else

{

printf("File Open successed!\n");

}

while(1)

{

read_len = fread(file_buffer, 1, 16, file_fd);

if(read_len == -1)

{

printf("File read error!\n");

perror("errno");

exit(0);

}

else if(read_len == 0)

{

printf("File read Over!\n");

break;

}

else

{

printf("Read %d Byte From download.bin: ",read_len);

for(i = 0; i < read_len; i++)

{

printf(" %02x",file_buffer[i]);

}

printf("\n");

}

usleep(20000);

}

fclose(file_fd);

return 0;

}

3、freopen

函數原型:FILE * freopen ( const char * filename, const char * mode, FILE * stream );

參數

filename: 要打開的文件名

mode: 文件打開的模式,和fopen中的模式(r/w)相同

stream: 文件指針,通常使用標準流文件(stdin/stdout/stderr)

返回值:如果成功則返回該指向該stream的指針,否則為NULL。

作用:用于重定向輸入輸出流的函數,將stream中的標準輸入、輸出、錯誤或者文件流重定向為filename文件中的內容。linux下需要重定向輸出很容易使用 ./程序名 >test (>>test 追加),windows下的輸入輸出重定向可以使用freopen。

使用方法:因為文件指針使用的是標準流文件,因此我們可以不定義文件指針。

我們使用freopen()函數以只讀方式r(read)打開輸入文件test.in ,freopen("test.in", "r", stdin);

這樣程序的輸入就會從標準輸入流stdin轉換到從文件"test.in"中輸入

然后使用freopen()函數以寫入方式w(write)打開輸出文件test.out,freopen("test.out", "w", stdout);

程序的輸出就會從原來的標準輸出變成寫入文件"test.out"中

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,785評論 18 139
  • C/C++輸入輸出流總結 前兩天寫C++實習作業,突然發現I/O是那么的陌生,打了好長時間的文件都沒有打開,今天終...
    LuckTime閱讀 1,747評論 0 6
  • 文件操作 (Linux文件操作)) [文件|目錄] Linux文件操作:為了對文件和目錄進程處理,你需要用到系統...
    JamesPeng閱讀 1,480評論 1 5
  • ### main函數執行之前做了什么?(iOS) & dyld 是Apple 的動態鏈接器;在 xnu 內核為程...
    天使君閱讀 697評論 0 1
  • 我是天蝎座的人,特點就是愛思考,愛學習,愛摸索的人。 我為什么如此的努力?也是因為我思想上比較理智。從上學開始,我...
    王寶玲閱讀 167評論 0 0