1. 程式人生 > >5-9 c語言之【文件】

5-9 c語言之【文件】

txt文件 勿噴 沒有 單元 形式 的區別 模塊 tro 這一

最近學習了在c語言中對文件的處理(此為win10操作系統),由根據《c標準庫》一書針對文件處理相關函數進行了一些總結

在這裏只總結了<stdio.h>頭文件內的函數,頭文件<stdio.h>聲明了很多執行輸入輸出的函數,在閱讀各個函數的定義即作用之前,章節前對於stdio.h的歷史追朔讓我很感興趣,甚至感覺 了解語言是如何進化統一的比了解函數語句是如何操作的更加重要,現將一部分內容節選出來分享一下:

在20世紀60年代早期,FORTRAN IV被認為是獨立於機器的語言。但是如果不作任何改動,根本不可能在各種計算機體系結構中移動FORTRAN IV程序。可移植性的主要障礙是輸入輸出領域。在FORTRAN IV中,可以對FORTRAN IV代碼中間的I/O語句中對正在通信的設備進行命名。CARD 和 INPUT TAPE就不一樣。

之後,逐漸發展到使用邏輯單元號(LUN)來代替具體的設備名,從而在可執行的二進制卡片之前加入控制卡片,從而指定某個特殊的運行過程那些設備與特定的LUN相對應。這時候,獨立於設備的I/O時代來臨了。

設備獨立的進一步改善得益於標準外圍交換程序(peripheral interchange program,PIP)的進步。該程序允許指定源設備與目標設備的任意成,然後盡力執行兩個設備之間的拷貝操作。

進入UNIX。UNIX對所有文本流采用了標準內部形式,文本的每一行以換行符終止。這正是程序讀入文本時所期望的,也是程序輸出所產生的。假如這樣的約定不能滿足和UNIX機器相連的處理文本的外圍設備的需求,可以在系統的對外接口有些修改,不必修改任何內部代碼。UNIX提供了兩種機制來修正“對外接口”的文本流。首先的是一個通用的映射函數,它可以用任意的文本處理設備工作。可以用系統調用ioctl來設置或者測試一個具體設備的的各種參數。另一個修正文本流的機制是修改直接控制該設備的專門軟件。對於每一個UNIX可能需要控制的設備來說,用戶必須添加一個常駐UNIX的設備管理器。

當第一個C編譯器在UNIX平臺上運行時,C語言就自然地繼承了它的宿主操作系統簡單的I/O模型。除了文本流的統一表示,還有其他一些優點。很久以前使用的LUNs在最近幾十年也慢慢地演變為稱為文件描述符或句柄的非常小的正整數。操作系統負責分發文件描述符。並且把所有的文件控制信息存儲在自己的專用內存中,而不是讓用戶去分配和維持文件和記錄控制塊以加重負擔。

為了簡化多數程序的運行管理,UNIX shell分配給每個運行的程序3個標準文件描述符,這些就是現在普通使用的標準輸入、標準輸出和標準錯誤流。(文本流)

UNIX不會阻止向任意打開的文件寫入任意的二進制編碼,或者從一個足夠大的地方把它們絲毫不變地讀取出來。(二進制流)

所以,UNIX消除了文本流(與人通信)和二進制流(與機器通信)之間的區別。

在相同的實現下,從一個二進制流讀入的數據應該和之前寫入到這個liu的數據相同,而文本流則不是。

PS:流是一個操作系統層面的高度抽象的概念,它隱藏了I/O設備具體的實質,而將所有的I/O帶來的數據變化看做輸入的流入和流出,這樣,在操作系統層面為程序將各種I/O設備模擬成流的樣式,已經使這時的I/O模塊獨立而抽象了。可以看到,I/O模型發展的過程,就是其逐漸抽象統一的過程,這一點與語言的發展的歷程是相似的。

X3J11委員會在1983年開始召開會議為C起草ANSI標準。非UNIX系統的C廠商和那些UNIX用戶之間爭論了很長時間,因為UNIX用戶不能理解I/O為什麽要這麽麻煩(顯然,UNIX的文件結構和設備的管理機制保證了I/O模塊的簡潔性,這是相對於其他操作系統的優點)。這是一個很有教育意義的過程,這些爭論的一個重要的副產品就是更清楚地闡明了C支持的I/O模塊。

最終,委員會經過討論整潔的重要性和向下兼容的重要性之後,決定拋棄UNIX風格的原語。(主要平衡代碼效率和代碼簡潔性)

接下來就看一下相關的實現

FILE 它是一個對象類型,可以記錄控制流需要的所有信息,包括它的文件定位符、指向相關緩沖(如果有的話)的指針、記錄是否發生了讀/寫錯誤的錯誤提示符和記錄文件手否結束的文件結束符(用來控制流的FILE對象的地址可能很重要,不必使用FILE對象的副本來代替原始的對象進行服務。

庫中的函數分兩類:

1.針對任意流的操作;

2.指定特定問文件流的操作;

兩者分別又有讀寫、文件定位、緩沖區控制等操作,可以完成對流的全方位操作。

文件只為兩種形式,字符型文件和二進制型文件

所以不管是何種形式的文件,c語言統一把它當作連續的字節流進行處理,該字節流的信息以及文件對應的文件描述符等都是需要存儲在FILE類型中的內容。

源碼的定義

 1 #ifndef _FILE_DEFINED
 2 struct _iobuf {
 3         char *_ptr;
 4         int   _cnt;
 5         char *_base;
 6         int   _flag;
 7         int   _file;
 8         int   _charbuf;
 9         int   _bufsiz;
10         char *_tmpfname;
11         };
12 typedef struct _iobuf FILE;

不需要對內部進行太多的理解,就是各種描述文件的信息,可以當作類似於int類型 一樣的類型去使用,只不過是描述文件類型

1.remove(導致一個文件再也不能通過它的文件名進行訪問)

 1 #include<stdio.h>
 2 int main()
 3 {
 4     FILE *pFile;
 5     char *FileName = "D:\\test1.txt";
 6     int n;
 7     int b;
 8     char buff[1024] = {0};
 9     b = remove(FileName);
10     fopen_s(&pFile,"D:\\test1.txt","r+");
11     //printf("%s    n = %d\n",buff,n);
12 
13     
14     return 0;
15 }

2.rename(類似於重命名)

 1 #include<stdio.h>
 2 int main()
 3 {
 4     char *pOld = "D:\\love.txt";
 5     char *pNew = "D:\\666.txt";
 6     FILE *pFile;
 7     rename(pOld,pNew);                                    //類似於重命名
 8     fopen_s(&pFile,"D:\\love.txt","r");
 9     return 0;
10 }

3.tmpfile(創建一個二進制的臨時文件)

4.fclose(清空流)

5.fopen(打開文件)

6.freopen(關聯文件,在編程比賽過程中,如果太過於繁雜的輸入數據,可以通過創建txt文件然後關聯的方式進行輸入,例 a + b)

 1 #include <stdio.h> 
 2 int main() 
 3 { 
 4     int a,b; 
 5     freopen("D:\\in.txt","r",stdin); //輸入數據將從in.txt文件中讀取 
 6     freopen("D:\\out.txt","w",stdout); //輸出數據將保存在out.txt文件中 
 7     while(scanf("%d %d",&a,&b)!=EOF) 
 8     printf("%d\n",a+b); 
 9     fclose(stdin);//關閉文件 
10     fclose(stdout);//關閉文件 
11     return 0; 
12 
13 } 

還有一些沒有涉及到的函數,在以後使用中繼續加入,接下來根據這些函數寫兩個簡單的應用

1.復制字符型文件

#include<stdio.h>
int main()
{
    FILE *pFile1;
    FILE *pFile2;
    char c;

    fopen_s(&pFile1,"D:\\test2.txt","r");
    fopen_s(&pFile2,"D:\\love.txt","w");
    while((c = getc(pFile1)) != EOF)
    {
        putc(c,pFile2);
    }

    return 0;
}

2.復制二進制型文件(也是文件傳輸的雛形)

#include<stdio.h>
int main()
{
    FILE *pFile1;
    FILE *pFile2;
    int n;
    char buff[1024];

    fopen_s(&pFile1,"C:\\Users\\cyc\\Desktop\\通訊錄-2.png","rb");
    fopen_s(&pFile2,"D:\\你猜是啥呀.png","wb");

    while((n = fread(buff,1,1024,pFile1))> 0)
    {
        fwrite(buff,1,n,pFile2);
    }
    return 0;
}

當然這個復制和快捷鍵 ctrl + c ctrl + v不同,快捷鍵是利用剪切板進行復制粘貼的

2019-05-09 11:34:21 編程小菜鳥自我反省,大佬勿噴,謝謝!!!

5-9 c語言之【文件】