日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

文件的输入/输出操作

發(fā)布時(shí)間:2023/11/30 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 文件的输入/输出操作 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

10.1 文件I/O操作概述

在Linux系統(tǒng)中,文件I/O操作可以分為兩類,一類是基于文件描述符的I/O操作,另一類是基于數(shù)據(jù)流的I/O操作。

10.1.1 文件描述符簡(jiǎn)介

在文件操作一章中,也經(jīng)常提到文件描述符這個(gè)概念。所謂文件描述符,就是進(jìn)程與打開(kāi)的文件的一個(gè)橋梁,通過(guò)這個(gè)橋梁,才可以在進(jìn)程中對(duì)這個(gè)文件進(jìn)行讀寫(xiě)等操作。

在Linux環(huán)境下,每打開(kāi)一個(gè)磁盤(pán)文件,都會(huì)在內(nèi)核中建立一個(gè)文件表項(xiàng),文件表項(xiàng)中存儲(chǔ)著文件的狀態(tài)信息、存儲(chǔ)文件內(nèi)容的緩沖區(qū)和當(dāng)前文件的讀寫(xiě)位置。如果同一磁盤(pán)文件打開(kāi)了3次,就會(huì)創(chuàng)建3個(gè)這樣的文件表項(xiàng)(a,b和c),讀寫(xiě)文件時(shí),只會(huì)改變?cè)撐募眄?xiàng)中的文件讀寫(xiě)位置。這3個(gè)文件表項(xiàng)存儲(chǔ)在一個(gè)文件表數(shù)組table[3]中,在這里table[0]=a,table[1]=b,table[2]=c。這個(gè)文件表的下標(biāo)就稱之為文件描述符,將這個(gè)文件描述符存儲(chǔ)在一個(gè)數(shù)組中des[3]={0,1,2},那么,在進(jìn)程中就可以通過(guò)這個(gè)des數(shù)組下標(biāo)引用文件表項(xiàng)。也就是說(shuō),通過(guò)文件描述符就可以訪問(wèn)到這個(gè)磁盤(pán)文件。

10.1.2 數(shù)據(jù)流概述

從數(shù)據(jù)操作方式這個(gè)角度來(lái)說(shuō),Linux系統(tǒng)中的文件(無(wú)論是普通文件還是設(shè)備文件)可以看做是數(shù)據(jù)流。對(duì)文件進(jìn)行操作之前,必須先調(diào)用標(biāo)準(zhǔn)I/O庫(kù)函數(shù)fopen()將數(shù)據(jù)流打開(kāi)。打開(kāi)數(shù)據(jù)流之后,就可以對(duì)數(shù)據(jù)流進(jìn)行輸入和輸出的操作。

標(biāo)準(zhǔn)I/O庫(kù)函數(shù)是C語(yǔ)言中所特有的用于高級(jí)接口的函數(shù),這些庫(kù)函數(shù)存放在C語(yǔ)言的stdio.h頭文件中,因此這些用于數(shù)據(jù)流的I/O操作函數(shù)不僅適用于Linux系統(tǒng),還適用于其他的操作系統(tǒng)。由此可見(jiàn),此庫(kù)函數(shù)的引用大大增加了程序的移植性。

要對(duì)數(shù)據(jù)流進(jìn)行讀寫(xiě)操作時(shí),需要標(biāo)準(zhǔn)I/O庫(kù)函數(shù)和FILE類型的文件指針一起來(lái)實(shí)現(xiàn)。這個(gè)文件指針石達(dá)開(kāi)數(shù)據(jù)流時(shí)返回的指針,該指針用來(lái)表示要操作的數(shù)據(jù)流。

當(dāng)執(zhí)行程序時(shí),有3個(gè)數(shù)據(jù)流不需要特定的函數(shù)進(jìn)行打開(kāi)的操作,他們會(huì)自動(dòng)打開(kāi)。這3個(gè)數(shù)據(jù)流是標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出。他們是自動(dòng)打開(kāi)的,當(dāng)不使用時(shí),也會(huì)自動(dòng)關(guān)閉。

然而,調(diào)用標(biāo)準(zhǔn)I/O庫(kù)函數(shù)fopen()打開(kāi)的數(shù)據(jù)流,在對(duì)數(shù)據(jù)流進(jìn)行操作后,需要調(diào)用fclose()函數(shù)將其關(guān)閉。fclose()函數(shù)在關(guān)閉數(shù)據(jù)流之前,會(huì)清空在操作過(guò)程中分配的緩沖區(qū)并保存數(shù)據(jù)信息。

10.2 基于文件描述符的I/O操作

10.2.1 文件的打開(kāi)與關(guān)閉

1)open()函數(shù)

#include<sys/types.h>

#include<sys/stat.h>

#include<fcntl.h>

int open(const char *pathname, int flags)

int open(const char *pathname, int flags, mode_t mode)

int creat(const char *pathname, mode_t mode)

上述的兩個(gè)open()函數(shù)和一個(gè)creat()函數(shù)在調(diào)用成功時(shí),都會(huì)返回其新分配的文件描述符;否則返值為-1,并設(shè)置適當(dāng)?shù)膃rror。

2)close()函數(shù)

#incldue<unistd.h>

int close(int fd)

當(dāng)一個(gè)進(jìn)程終止時(shí),內(nèi)核對(duì)該進(jìn)程的所有尚未關(guān)閉的文件描述符調(diào)用close()函數(shù)關(guān)閉,所以即使用戶程序不調(diào)用close()函數(shù),在終止時(shí)內(nèi)核也會(huì)自動(dòng)關(guān)閉它打開(kāi)的所有文件。但是,對(duì)于網(wǎng)絡(luò)服務(wù)器這種一直運(yùn)行的程序,文件描述符一定要及時(shí)關(guān)閉,否則隨著打開(kāi)的文件越來(lái)越多,會(huì)占用大量文件描述符和系統(tǒng)資源。

有函數(shù)open()返回的文件描述符一定是該進(jìn)程尚未使用的最小描述符。由于程序啟動(dòng)時(shí)自動(dòng)打開(kāi)標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出,因此文件描述符0,1,2會(huì)存在,那么第一次調(diào)用open()函數(shù)打開(kāi)文件時(shí)返回的文件描述符通常會(huì)是3,再調(diào)用open()函數(shù)就會(huì)返回4.可以利用這一點(diǎn)在標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出或標(biāo)準(zhǔn)錯(cuò)誤輸出上打開(kāi)一個(gè)新文件,是想重定向的功能。例如,首先調(diào)用close()函數(shù)關(guān)閉文件描述符1,然后調(diào)用open()函數(shù)打開(kāi)一個(gè)常規(guī)文件,則一定會(huì)返回文件描述符1,這是標(biāo)準(zhǔn)輸出就不再是終端,而是一個(gè)常規(guī)文件了,再調(diào)用printf()函數(shù)就不打印到屏幕上,而是寫(xiě)到這個(gè)文件中了。在文件操作一章中講到的dup2()函數(shù)就是另外一種在指定的文件描述符上打開(kāi)文件的方法。

10.2.2 文件的讀寫(xiě)操作

1)read()函數(shù)

#include<unistd.h>

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

2)write()函數(shù)

#include<unistd.h>

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

10.2.3 文件的定位

每個(gè)文件都記錄著當(dāng)前讀寫(xiě)位置,打開(kāi)文件時(shí)讀寫(xiě)位置是0,表示文件開(kāi)頭,通常讀寫(xiě)多少個(gè)自己就會(huì)將讀寫(xiě)位置往后移多少個(gè)字節(jié)。

以O(shè)_APPEND方式打開(kāi)文件,每次寫(xiě)操作都會(huì)在文件末尾追加數(shù)據(jù),然后間讀寫(xiě)位置移動(dòng)到新的文件末尾。

1)lseek()函數(shù)

lseek()函數(shù)可以移動(dòng)當(dāng)前讀寫(xiě)位置,通常稱為偏移量,該函數(shù)的定義形式如下:

#include<sys/types.h>

#include<unisd.h>

off_t lseek(int fildes, off_t offset, int whence)

10.3 基于數(shù)據(jù)流的I/O操作

10.3.1 文件的打開(kāi)與關(guān)閉

在操作文件之前要用fopen()函數(shù)打開(kāi)文件,操作結(jié)束后,要用fclose()函數(shù)關(guān)閉文件。

1)fopen()函數(shù)

#include<stdio.h>

FILE *foepn(cosnt char *path, cosnt char *mode)

2)fclose()函數(shù)

#include<stdio.h>

int fclose(FILE *fp)

10.3.2 字符輸入/輸出

1)fgetc()函數(shù)

fgetc()函數(shù)從指定的文件中讀一個(gè)字節(jié),該函數(shù)的定義形式如下:

#include<stdio.h>

int fgetc(FILE *stream)

在程序中,偶爾會(huì)遇到getchar()函數(shù),也是用于讀取一個(gè)字節(jié),但它是從標(biāo)準(zhǔn)輸入讀一個(gè)字節(jié)。在程序中調(diào)用getchar()函數(shù)相當(dāng)于調(diào)動(dòng)fgetc(stdin)

在使用fgetc()函數(shù)時(shí)需要注意一下幾點(diǎn):

①調(diào)用fgetc()函數(shù)時(shí),指定的文件的打開(kāi)方式必須是可讀的。

②函數(shù)fgetc()調(diào)用成功時(shí),返回的是讀到的字節(jié),應(yīng)該為unsigned char,但fgetc()函數(shù)在原型中返回值類型時(shí)int,原因在于函數(shù)調(diào)用出錯(cuò)或讀到文件末尾時(shí)fgetc()會(huì)返回EOF,即-1,保存在int型的返回值是0xffffffff,如果讀到字節(jié)0xff,由unsigned char型轉(zhuǎn)換int 型時(shí)0x000000ff,只有規(guī)定返回值是int型才能把這種情況區(qū)分開(kāi),如果規(guī)定返回值是unsigned char型,那么當(dāng)返回值是0xff時(shí)則無(wú)法區(qū)分到底是EOF還是字節(jié)0xff。

2)fputc()函數(shù)

#include<stdio.h>

int fputc(int c, FILE *stream)

10.3.3 字符串輸入/輸出

1)fgets()函數(shù)

#include<stdio.h>

char *fgets(char *s, int size, FILE *stream)

對(duì)于fgets()函數(shù)而言,'\n'是一個(gè)特別的字符,作為結(jié)束符;而'\0'并無(wú)任何特別之處,只用作普通字符串讀入。正因?yàn)?#39;\0'作為一個(gè)普通的字符串,因此無(wú)法判斷緩沖區(qū)中的'\0'究竟是從文件讀上來(lái)的字符還是有fgets()函數(shù)自主添加的結(jié)束符,所以fgets()函數(shù)只用于讀文本文件而不提倡讀二進(jìn)制文件,并且文本文件中的所有字符串不能有'\0'。

2)fputs()

#include<stdio.h>

int fputs(const char *s, FILE *stream)

緩沖區(qū)s中保存的是以'\0'結(jié)尾的字符串,fputs()將該字符串寫(xiě)入文件stream,但并不寫(xiě)入結(jié)尾的'\0',且字符串中可以有'\n',也可以沒(méi)有'\n'。

10.3.4 數(shù)據(jù)塊輸入/輸出

1)fread()和fwrite()函數(shù)

#include<stido.h>

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)

10.3.5 格式化輸入/輸出

所謂格式化輸入/輸出,就是按照一定的格式將數(shù)據(jù)進(jìn)行輸入/輸出操作。在程序中經(jīng)常用到的printf()函數(shù)和scanf()函數(shù)是用于對(duì)終端設(shè)備文件的讀寫(xiě)操作,這兩個(gè)函數(shù)被稱為格式化輸入/輸出,因?yàn)樵谑褂眠@兩個(gè)函數(shù)時(shí),需要制定讀寫(xiě)數(shù)據(jù)的數(shù)據(jù)類型并按照一定的格式進(jìn)行讀寫(xiě)。

1)格式化輸入函數(shù)

#include<stdio.h>

int printf(const char *format,...)

int fprintf(FILE *stream, const char *format)

int sprintf(char *str, size_t size, const char *format,...)

2)格式化輸出函數(shù)

#include<stdio.h>

int scanf(const char *format,...)

int fscanf(FILE *stream, const char *format,...)

int sscanf(const char *str, const char *format,...)

10.3.6 操作讀寫(xiě)位置的函數(shù)

1)fseek()函數(shù)

#inlcude<stdio.h>

int fseek(FILE *stream, long offset, int whence)

函數(shù)fseek()的作用是用來(lái)移動(dòng)文件內(nèi)部位置指針。

2)ftell()函數(shù)

#inlcude<stdio.h>

long ftell(FILE *stream)

ftell()函數(shù)的作用是得到stream指定的流式文件中的位置。

3)rewind()函數(shù)

void rewind(FILE *stream)

rewind()函數(shù)的作用是使位置指針重新返回文件的開(kāi)頭,該函數(shù)沒(méi)有返回值。

10.3.7 C標(biāo)準(zhǔn)的I/O緩沖區(qū)

C標(biāo)準(zhǔn)庫(kù)在調(diào)用fopen()函數(shù)時(shí),都會(huì)給此文件分配一個(gè)I/O緩沖區(qū),可以加速讀寫(xiě)操作,原因在于用戶程序需要調(diào)用C標(biāo)準(zhǔn)I/O庫(kù)函數(shù)(如fread()、fwrite()等基于文件流I/O操作)讀寫(xiě)文件,當(dāng)緩沖區(qū)裝滿后,再由系統(tǒng)調(diào)用的I/O函數(shù)(如read()、write()等基于文件描述符的I/O操作)把讀寫(xiě)請(qǐng)求傳給內(nèi)核,最終由內(nèi)核驅(qū)動(dòng)磁盤(pán)或設(shè)備完成I/O操作。

由此看來(lái),為文件分配的內(nèi)存緩沖區(qū)大小,直接影響到實(shí)際操作外村設(shè)備的次數(shù),內(nèi)存中為未見(jiàn)分配的緩沖區(qū)越大,操作外存的次數(shù)會(huì)越小,因此讀寫(xiě)數(shù)據(jù)的速度會(huì)越來(lái)越快,效率就會(huì)隨之增高。

然而,有時(shí)用戶程序等不及將緩沖區(qū)都裝滿之后再傳給內(nèi)核,進(jìn)行I/O操作,而是希望把I/O緩沖區(qū)中的數(shù)據(jù)立刻傳給內(nèi)核,讓內(nèi)核寫(xiě)回設(shè)備,這種行為叫做flush操作,對(duì)應(yīng)的庫(kù)函數(shù)是fflush()。

C標(biāo)準(zhǔn)庫(kù)的I/O緩沖區(qū)有全緩沖、行緩沖和無(wú)緩沖3種類型。

1)全緩沖:如果緩沖區(qū)寫(xiě)滿了,就寫(xiě)回內(nèi)核。普通文件通常是全緩沖的。

2)行緩沖:如果用戶程序?qū)懙臄?shù)據(jù)中有'\n',就把這一行寫(xiě)回內(nèi)核,或者緩沖區(qū)寫(xiě)滿后就寫(xiě)回內(nèi)核。標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出對(duì)應(yīng)中斷設(shè)備時(shí)通常是行緩沖。

3)無(wú)緩沖:用戶程序每次調(diào)庫(kù)函數(shù)做寫(xiě)操作都要通過(guò)系統(tǒng)調(diào)用寫(xiě)回內(nèi)核。標(biāo)準(zhǔn)錯(cuò)誤輸出通常是無(wú)緩沖的。這樣用戶程序產(chǎn)生的錯(cuò)誤信息就可以盡快輸出到設(shè)備。

使用緩沖區(qū)時(shí),會(huì)使用到如下兩類操作,一個(gè)是設(shè)置緩沖區(qū)屬性,另外一個(gè)是清空緩沖區(qū)。

4)設(shè)置緩沖區(qū)屬性

#include<stdio.h>

void setbuf(FILE *stream, char *buf)

void setbuffer(FILE *stream, char *buf, size_t size)

void setlinebuf(FILE *stream)

int setvbuf(FILE *stream, char *buf, int mode, size_t size)

setbuf()函數(shù)主要實(shí)現(xiàn)了為參數(shù)buf所指定的緩沖區(qū)設(shè)置大小。此函數(shù)中,設(shè)定緩沖區(qū)大小的值只有兩個(gè),一個(gè)是常數(shù)BUFSIZ,另一個(gè)是NULL。當(dāng)定義值為BUFSIZ時(shí),代表設(shè)置緩沖區(qū)為全緩沖;若為NULL,則代表設(shè)置緩沖區(qū)為無(wú)緩沖形式。

setbuffer()與setbuf()功能相同,只是setbuffer()函數(shù)可以任意指定緩沖區(qū)大小為size

setlinebuf()函數(shù)實(shí)現(xiàn)了將stream指向的緩沖區(qū)設(shè)置為行緩沖。

setvbuf()函數(shù)融合了上述3種函數(shù)的功能,既可以設(shè)置緩沖區(qū)的任意大小size,也可以設(shè)置緩沖區(qū)的任意類型,如mode參數(shù)取值為_(kāi)IOFBF(全緩沖類型)、_IOLBF(行緩沖類型)或_IONBF(無(wú)緩沖類型)。

5)清空緩沖區(qū)

#include<stdio.h>

int fflush(FILE *stream)

fflush()函數(shù)實(shí)現(xiàn)將緩沖區(qū)中的尚未寫(xiě)入文件的數(shù)據(jù)強(qiáng)制性地寫(xiě)進(jìn)stream所指定的文件中,然后清空緩沖區(qū)。如果stream為NULL,此函數(shù)會(huì)將所有打開(kāi)的文件數(shù)據(jù)更新。

10.4 小結(jié)

本章主要介紹了Linux系統(tǒng)下的文件I/O操作。在Linux系統(tǒng)下存在兩種文件I/O操作,一種是基于文件描述符的I/O操作,這里面的I/O操作都是Linux系統(tǒng)中提供并直接作用于內(nèi)核的,是非緩沖的I/O操作;另一種I/O操作是基于數(shù)據(jù)流的I/O操作,是由C語(yǔ)言的stdio庫(kù)所提供的,需要在內(nèi)存中開(kāi)辟一塊緩沖區(qū),在緩沖區(qū)中進(jìn)行快速地讀寫(xiě)操作。本章主要結(jié)合典型實(shí)例介紹了上述兩種I/O操作方式對(duì)文件的打開(kāi)、關(guān)閉、讀、寫(xiě)、文件定位等操作。

轉(zhuǎn)載于:https://www.cnblogs.com/zuixiaoyao/p/3530298.html

總結(jié)

以上是生活随笔為你收集整理的文件的输入/输出操作的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。