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

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

open是linux下的底層系統(tǒng)調(diào)用函數(shù),fopen與freopen c/c++下的標(biāo)準(zhǔn)I/O庫(kù)函數(shù),帶輸入/輸出緩沖。

linxu下的fopen是open的封裝函數(shù),fopen最終還是要調(diào)用底層的系統(tǒng)調(diào)用open。

所以在linux下如果需要對(duì)設(shè)備進(jìn)行明確的控制,那最好使用底層系統(tǒng)調(diào)用(open),

open對(duì)應(yīng)的文件操作有:close, read, write,ioctl 等。

fopen對(duì)應(yīng)的文件操作有:fclose, fread, fwrite, freopen, fseek, ftell, rewind等。

freopen用于重定向輸入輸出流的函數(shù),該函數(shù)可以在不改變代碼原貌的情況下改變輸入輸出環(huán)境,但使用時(shí)應(yīng)當(dāng)保證流是可靠的。詳細(xì)見(jiàn)第3部分。

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

open和fopen的區(qū)別:

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

2,fopen是標(biāo)準(zhǔn)c里定義的,open是POSIX中定義的.

3,fread可以讀一個(gè)結(jié)構(gòu).read在linux/unix中讀二進(jìn)制與普通文件沒(méi)有區(qū)別.

4,fopen不能指定要?jiǎng)?chuàng)建文件的權(quán)限.open可以指定權(quán)限.

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

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

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

1、open系統(tǒng)調(diào)用(linux)

需要包含頭文件:#include

#include

#include

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

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

mode僅當(dāng)創(chuàng)建新文件時(shí)才使用,用于指定文件的訪問(wèn)權(quán)限。

pathname是待打開(kāi)/創(chuàng)建文件的路徑名;

oflags用于指定文件的打開(kāi)/創(chuàng)建模式,這個(gè)參數(shù)可由以下常量(定義于 fcntl.h)通過(guò)邏輯或構(gòu)成。

O_RDONLY ? ? ? 只讀模式

O_WRONLY ? ? ?只寫(xiě)模式

O_RDWR ? ? ? ? ?讀寫(xiě)模式

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

打開(kāi)/創(chuàng)建文件時(shí),至少得使用上述三個(gè)常量中的一個(gè)。以下常量是選用的:

O_APPEND ? ? ? ? 每次寫(xiě)操作都寫(xiě)入文件的末尾

O_CREAT ? ? ? ? ? ?如果指定文件不存在,則創(chuàng)建這個(gè)文件

O_EXCL ? ? ? ? ? ? ? 如果要?jiǎng)?chuàng)建的文件已存在,則返回 -1,并且修改 errno 的值

O_TRUNC ? ? ? ? ? 如果文件存在,并且以只寫(xiě)/讀寫(xiě)方式打開(kāi),則清空文件全部?jī)?nèi)容

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

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

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

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

O_RSYNC ? ? ? ? ?read 等待所有寫(xiě)入同一區(qū)域的寫(xiě)操作完成后再進(jìn)行

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

當(dāng)你使用帶有O_CREAT標(biāo)志的open調(diào)用來(lái)創(chuàng)建文件時(shí),你必須使用有3個(gè)參數(shù)格式的open調(diào)用。第三個(gè)參數(shù)mode是幾個(gè)標(biāo)志按位或后得到的,

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

S_IRUSR: ? ?讀權(quán)限,文件屬主

S_IWUSR: ? 寫(xiě)權(quán)限,文件屬主

S_IXUSR: ? ?執(zhí)行權(quán)限,文件屬主

S_IRGRP: ? ?讀權(quán)限,文件所屬組

S_IWGRP: ? 寫(xiě)權(quán)限,文件所屬組

S_IXGRP: ? ?執(zhí)行權(quán)限,文件所屬組

S_IROTH: ? 讀權(quán)限,其它用戶

S_IWOTH: ?寫(xiě)權(quán)限,其它用戶

S_IXOTH: ? 執(zhí)行權(quán)限,其它用戶

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

錯(cuò)誤代碼:(均已E開(kāi)頭,將其去掉就是有關(guān)于錯(cuò)誤的方面的單詞或單詞的縮寫(xiě))

EEXIST 參數(shù)pathname 所指的文件已存在,卻使用了O_CREAT和O_EXCL旗標(biāo)。

EACCESS 參數(shù)pathname所指的文件不符合所要求測(cè)試的權(quán)限。

EROFS 欲測(cè)試寫(xiě)入權(quán)限的文件存在于只讀文件系統(tǒng)內(nèi)。

EFAULT 參數(shù)pathname指針超出可存取內(nèi)存空間。

EINVAL 參數(shù)mode 不正確。ENAMETOOLONG 參數(shù)pathname太長(zhǎng)。

ENOTDIR 參數(shù)pathname不是目錄。

ENOMEM 核心內(nèi)存不足。

ELOOP 參數(shù)pathname有過(guò)多符號(hào)連接問(wèn)題。

EIO I/O 存取錯(cuò)誤。

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

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

參數(shù)

fd:要進(jìn)行寫(xiě)操作的文件描述詞。

buf:需要輸出的緩沖區(qū)

count:最大輸出字節(jié)計(jì)數(shù)

返回值:成功返回寫(xiě)入的字節(jié)數(shù),出錯(cuò)返回-1并設(shè)置errno

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

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

參數(shù)

buf:需要讀取的緩沖區(qū)

count:最大讀取字節(jié)計(jì)數(shù)

返回值:成功返回讀取的字節(jié)數(shù),出錯(cuò)返回-1并設(shè)置errno,如果在調(diào)read之前已到達(dá)文件末尾,則這次read返回0。

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

2、fopen庫(kù)函數(shù)

頭文件

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

path字符串包含欲打開(kāi)的文件路徑及文件名,參數(shù)mode字符串則代表著流形態(tài)。

mode有下列幾種形態(tài)字符串:

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

"w"或"wb" ? ? 以寫(xiě)方式打開(kāi)文件,并把文件長(zhǎng)度截短為零。

"a"或"ab" ? ? ?以寫(xiě)方式打開(kāi)文件,新內(nèi)容追加在文件尾。

"r+"或"rb+"或"r+b" ? ? ? 以更新方式打開(kāi)(讀和寫(xiě))

"w+"或"wb+"或"w+b" ? 以更新方式打開(kāi),并把文件長(zhǎng)度截短為零。

"a+"或"ab+"或"a+b" ? ? 以更新方式打開(kāi),新內(nèi)容追加在文件尾。

字母b表示文件時(shí)一個(gè)二進(jìn)制文件而不是文本文件。(linux下不區(qū)分二進(jìn)制文件和文本文件)

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

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

fread是一個(gè)函數(shù)。從一個(gè)文件流中讀數(shù)據(jù),最多讀取count個(gè)元素,每個(gè)元素size字節(jié),如果調(diào)用成功返回實(shí)際讀取到的元素個(gè)數(shù),如果不成功或讀到文件末尾返回 0。

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

參 數(shù):

buffer:用于接收數(shù)據(jù)的內(nèi)存地址

size:要讀寫(xiě)的字節(jié)數(shù),單位是字節(jié)

count:要進(jìn)行讀寫(xiě)多少個(gè)size字節(jié)的數(shù)據(jù)項(xiàng),每個(gè)元素是size字節(jié).

stream:輸入流

返回值:實(shí)際讀取的元素個(gè)數(shù).如果返回值與count不相同,則可能文件結(jié)尾或發(fā)生錯(cuò)誤,從ferror和feof獲取錯(cuò)誤信息或檢測(cè)是否到達(dá)文件結(jié)尾.

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

fwrite:向文件寫(xiě)入一個(gè)數(shù)據(jù)塊

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

參數(shù):

buffer:是一個(gè)指針,對(duì)fwrite來(lái)說(shuō),是要獲取數(shù)據(jù)的地址;

size:要寫(xiě)入內(nèi)容的單字節(jié)數(shù);

count:要進(jìn)行寫(xiě)入size字節(jié)的數(shù)據(jù)項(xiàng)的個(gè)數(shù);

stream:目標(biāo)文件指針;

返回值:返回實(shí)際寫(xiě)入的數(shù)據(jù)塊數(shù)目

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

fflush:把文件流里的所有為寫(xiě)出數(shù)據(jù)立刻寫(xiě)出。

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

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

fseek:是lseek系統(tǒng)調(diào)用對(duì)應(yīng)的文件流函數(shù)。它在文件流里為下一次讀寫(xiě)操作指定位置。

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

參數(shù)stream為文件指針

參數(shù)offset為偏移量,正數(shù)表示正向偏移,負(fù)數(shù)表示負(fù)向偏移

參數(shù)fromwhere設(shè)定從文件的哪里開(kāi)始偏移,可能取值為:SEEK_CUR、 SEEK_END 或 SEEK_SET

SEEK_SET: 文件開(kāi)頭

SEEK_CUR: 當(dāng)前位置

SEEK_END: 文件結(jié)尾

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

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

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

以下為linux下一個(gè)打開(kāi)文件并顯示文件內(nèi)容的程序:

#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

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

參數(shù)

filename: 要打開(kāi)的文件名

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

stream: 文件指針,通常使用標(biāo)準(zhǔn)流文件(stdin/stdout/stderr)

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

作用:用于重定向輸入輸出流的函數(shù),將stream中的標(biāo)準(zhǔn)輸入、輸出、錯(cuò)誤或者文件流重定向?yàn)閒ilename文件中的內(nèi)容。linux下需要重定向輸出很容易使用 ./程序名 >test (>>test 追加),windows下的輸入輸出重定向可以使用freopen。

使用方法:因?yàn)槲募羔樖褂玫氖菢?biāo)準(zhǔn)流文件,因此我們可以不定義文件指針。

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

這樣程序的輸入就會(huì)從標(biāo)準(zhǔn)輸入流stdin轉(zhuǎn)換到從文件"test.in"中輸入

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

程序的輸出就會(huì)從原來(lái)的標(biāo)準(zhǔn)輸出變成寫(xiě)入文件"test.out"中

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,695評(píng)論 19 139
  • C/C++輸入輸出流總結(jié) 前兩天寫(xiě)C++實(shí)習(xí)作業(yè),突然發(fā)現(xiàn)I/O是那么的陌生,打了好長(zhǎng)時(shí)間的文件都沒(méi)有打開(kāi),今天終...
    LuckTime閱讀 1,811評(píng)論 0 6
  • 文件操作 (Linux文件操作)) [文件|目錄](méi) Linux文件操作:為了對(duì)文件和目錄進(jìn)程處理,你需要用到系統(tǒng)...
    JamesPeng閱讀 1,613評(píng)論 1 5
  • ### main函數(shù)執(zhí)行之前做了什么?(iOS) & dyld 是Apple 的動(dòng)態(tài)鏈接器;在 xnu 內(nèi)核為程...
    天使君閱讀 779評(píng)論 0 1
  • 我是天蝎座的人,特點(diǎn)就是愛(ài)思考,愛(ài)學(xué)習(xí),愛(ài)摸索的人。 我為什么如此的努力?也是因?yàn)槲宜枷肷媳容^理智。從上學(xué)開(kāi)始,我...
    王寶玲閱讀 202評(píng)論 0 0

友情鏈接更多精彩內(nèi)容