您好,登錄后才能下訂單哦!
這篇文章主要介紹“C語言怎么處理fseek()和ftell()的I/O隨機訪問數”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“C語言怎么處理fseek()和ftell()的I/O隨機訪問數”文章能幫助大家解決問題。
有了fseek()
函數,便可把文件看作是數組,在fopen()
打開的文件中直接移動到任意字節處。我們創建一個程序reverse.c
演示fseek()
和ftell()
的用法。注意,fseek()
有3個參數,返回int
類型的值;ftell()
函數返回一個long
類型的值,表示文件中的當前位置。
/* reverse.c -- displays a file in reverse order */ #include <stdio.h> #include <stdlib.h> #define CNTL_Z '032' /* eof marker in DOS text files */ #define SLEN 81 int main(void) { char file[SLEN]; char ch; FILE *fp; long count, last; puts("Enter the name of the file to be processed:"); scanf("%80s", file); if ((fp = fopen(file,"rb")) == NULL) { /* read-only mode */ printf("reverse can't open %sn", file); exit(EXIT_FAILURE); } fseek(fp, 0L, SEEK_END); /* go to end of file */ last = ftell(fp); for (count = 1L; count <= last; count++) { fseek(fp, -count, SEEK_END); /* go backward */ ch = getc(fp); if (ch != CNTL_Z && ch != 'r') /* MS-DOS files */ putchar(ch); } putchar('n'); fclose(fp); return 0; }
下面是對一個文件的輸出:
Enter the name of the file to be processed: Cluv .C ni eno naht ylevol erom margorp a ees reven llahs I taht kniht I
該程序使用二進制模式,以便處理MS-DOS
文本和UNIX
文件。但是,在使用其他格式文本文件的環境中可能無法正常工作。
如果通過命令行環境運行該程序,待處理文件要和可執行文件在同一個目錄(或文件夾)中。如果在IDE中運行該程序,具體查找方案序因實現而異。例如,默認情況下,Microsoft Visual Studio 2012
在源代碼所在的目錄中查找,而Xcode 4.6
則在可執行文件所在的目錄中查找。
fseek()
的第1個參數是FILE
指針,指向待查找的文件,fopen()
應該已打開該文件。
fseek()
的第2個參數是偏移量(offset
)。該參數表示從起始點開始要移動的距離(參見表13.3列出的起始點模式)。該參數必須是一個long
類型的值,可以為正(前移)、負(后移)或0(保持不動)。
fseek()
的第3個參數是模式,該參數確定起始點。根據ANSI
標準,在stdio.h
頭文件中規定了幾個表示模式的明示常量(manifest constant
)
舊的實現可能缺少這些定義,可以使用數值0L、1L、2L
分別表示這3種模式。L
后綴表明其值是long
類型。或者,實現可能把這些明示常量定義在別的頭文件中。如果不確定,請查閱實現的使用手冊或在線幫助。
下面是調用fseek()
函數的一些示例,fp
是一個文件指針:
fseek(fp, 0L, SEEK_SET); // go to the beginning of the file fseek(fp, 10L, SEEK_SET); // go 10 bytes into the file fseek(fp, 2L, SEEK_CUR); // advance 2 bytes from the current position fseek(fp, 0L, SEEK_END); // go to the end of the file fseek(fp, -10L, SEEK_END); // back up 10 bytes from the end of the file
對于這些調用還有一些限制,我們稍后再討論。
如果一切正常,fseek()
的返回值為0;如果出現錯誤(如試圖移動的距離超出文件的范圍),其返回值為-1。
ftell()
函數的返回類型是long
,它返回的是參數指向文件的當前位置距文件開始處的字節數。ANSI-C
把它定義在stdio.h
中。在最初實現的UNIX
中,ftell()
通過返回距文件開始處的字節數來確定文件的位置。文件的第1個字節到文件開始處的距離是0,以此類推。ANSI C
規定,該定義適用于以二進制模式打開的文件,以文本模式打開文件的情況不同。這也是程序reverse.c
以二進制模式打開文件的原因。
下面,我們來分析程序reverse.c
中的基本要素。首先,下面的語句:
fseek(fp, 0L, SEEK_END);
把當前位置設置為距文件末尾0字節偏移量。也就是說,該語句把當前位置設置在文件結尾。下一條語句:
last = ftell(fp);
把從文件開始處到文件結尾的字節數賦給last
。然后是一個for
循環:
for (count = 1L; count <= last; count++) { fseek(fp, -count, SEEK_END); /* go backward */ ch = getc(fp); }
第1輪迭代,把程序定位到文件結尾的第1個字符(即,文件的最后一個字符)。然后,程序打印該字符。下一輪迭代把程序定位到前一個字符,并打印該字符。重復這一過程直至到達文件的第1個字符,并打印。
我們設計的程序reverse.c
在UNIX
和MS-DOS
環境下都可以運行。UNIX
只有一種文件格式,所以不需要進行特殊的轉換。然而MS-DOS
要格外注意。許多MS-DOS
編輯器都用Ctrl+Z
標記文本文件的結尾。以文本模式打開這樣的文件時,C
能識別這個作為文件結尾標記的字符。但是,以二進制模式打開相同的文件時,Ctrl+Z
字符被看作是文件中的一個字符,而實際的文件結尾符在該字符的后面。文件結尾符可能緊跟在Ctrl+Z
字符后面,或者文件中可能用空字符填充,使該文件的大小是256的倍數。在DOS
環境下不會打印空字符,程序reverse.c
中就包含了防止打印Ctrl+Z
字符的代碼。
二進制模式和文本模式的另一個不同之處是:MS-DOS
用\r\n
組合表示文本文件換行。以文本模式打開相同的文件時,C
程序把\r\n
“看成”\n
。但是,以二進制模式打開該文件時,程序能看見這兩個字符。因此,程序reverse.c
中還包含了不打印\r
的代碼。通常,UNIX
文本文件既沒有Ctrl+Z
,也沒有\r
,所以這部分代碼不會影響大部分UNIX
文本文件。
ftell()
函數在文本模式和二進制模式中的工作方式不同。許多系統的文本文件格式與UNIX
的模型有很大不同,導致從文件開始處統計的字節數成為一個毫無意義的值。ANSI C
規定,對于文本模式,ftell()
返回的值可以作為fseek()
的第2個參數。對于MS-DOS
,ftell()
返回的值把\r\n
當作一個字節計數。
理論上,fseek()
和ftell()
應該符合UNIX
模型。但是,不同系統存在著差異,有時確實無法做到與UNIX
模型一致。因此,ANSI
對這些函數降低了要求。下面是一些限制。
在二進制模式中,實現不必支持SEEK_END
模式。因此無法保證程序清單13.4的可移植性。移植性更高的方法是逐字節讀取整個文件直到文件末尾。C預處理器的條件編譯指令(第16章介紹)提供了一種系統方法來處理這種情況。
在文本模式中,只有以下調用能保證其相應的行為。
fseek()
和ftell()
潛在的問題是,它們都把文件大小限制在long
類型能表示的范圍內。也許20億字節看起來相當大,但是隨著存儲設備的容量迅猛增長,文件也越來越大。鑒于此,ANSI C
新增了兩個處理較大文件的新定位函數:fgetpos()
和fsetpos()
。這兩個函數不使用long
類型的值表示位置,它們使用一種新類型:fpos_t
(代表file positiontype,文件定位類型)。fpos_t
類型不是基本類型,它根據其他類型來定義。fpos_t
類型的變量或數據對象可以在文件中指定一個位置,它不能是數組類型,除此之外,沒有其他限制。實現可以提供一個滿足特殊平臺要求的類型,例如,fpos_t
可以實現為結構。
ANSI-C
定義了如何使用fpos_t
類型。fgetpos()
函數的原型如下:
nt fgetpos(FILE * restrict stream, fpos_t * restrict pos);
調用該函數時,它把fpos_t
類型的值放在pos
指向的位置上,該值描述了文件中的當前位置距文件開頭的字節數。如果成功,fgetpos()
函數返回0;如果失敗,返回非0。
fsetpos()
函數的原型如下:
: int fsetpos(FILE stream, const fpos_t pos);
調用該函數時,使用pos
指向位置上的fpos_t
類型值來設置文件指針指向偏移該值后指定的位置。如果成功,fsetpos()
函數返回0;如果失敗,則返回非0。fpos_t
類型的值應通過之前調用fgetpos()
獲得。
關于“C語言怎么處理fseek()和ftell()的I/O隨機訪問數”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。