C語言基礎及指針⑧文件IO

接續上篇C語言基礎及指針⑦結構體與指針
在結構體與指針中 , 我們了解到結構體與java中的類相似 , 也是一種自定義類型數據結構 , 也學習了結構的各種用法 , 以及簡單的應用 。

在編寫應用程序的時候 , 文件IO操作是不可避免的 , 小到日志本地化收集 , 大到數據格式化存儲 , 都需要使用文件IO , 來操作文件流進行數據處理 。在使用java開發的時候 , 我們有File類和FileReader,FileWriter類來搭配使用 , 也有FileInputStream,FileOutputStreamBufferedInputStream,BufferedOutputStream金牌組合 。使得java中的文件IO很方便 , 下面我們就來看看簡單的java文件IO示例:

     // 讀取文件中的字符
    private static void readString() throws Exception{
        File _file = new File("e:"+separetor+"a.txt") ;
        if (!_file.exists()) {
            boolean createStatuts = _file.createNewFile() ;
            if (createStatuts) {
                System.out.println("創建了一個新文件 ,并且創建成功了");
            }else {
                System.out.println("創建新文件失敗");
            }
        }
        
        // 創建輸入流
        InputStream fileInputStream = new FileInputStream(_file) ;
        byte[] bytes = new byte[1024] ;
        int len = -1;
        StringBuffer buffer = new StringBuffer() ;
        while ((len = fileInputStream.read(bytes)) != -1) {
            buffer.append(new String(bytes,0,len)) ;
        }
        // 關閉輸入流
        fileInputStream.close() ;
        
        System.out.println(buffer.toString());
    }

    // 將字符串寫入文件
    private static void writeString() throws Exception{
        File _file = new File("e:"+separetor+"a.txt") ;
        if (!_file.exists()) {
            boolean createStatuts = _file.createNewFile() ;
            if (createStatuts) {
                System.out.println("創建了一個新文件 ,并且創建成功了");
            }else {
                System.out.println("創建新文件失敗");
            }
        }
        
        // 創建輸出流
        OutputStream fileOutputStream = new FileOutputStream(_file) ;
        String info = "《op 青空 pure rouge 君吻》《君吻 その目に映るもの piano》" ;
        fileOutputStream.write(info.getBytes()) ;
        // 關閉輸出流
        fileOutputStream.close() ;
        
    }

文件IO操作步驟:

1.創建一個File對象(需要操作的文件)
2.構建輸入輸出流
3.創建緩沖區 , 緩存讀寫數據 (將流數據讀入到內存或寫入到磁盤)
3.關閉流 (關閉文件流)

語言都是相通的 , 在C語言中文件IO的操作也是如上述幾步 , 下面我們就一起來看看:

/*讀取文本文件*/
void readTextFile() {
    char* path = "C:\\Users\\Zeno\\Documents\\Visual Studio 2015\\Projects\\Hello_C\\Hello_C\\StructPointer.c";

    // 打開文件
    FILE* fp = fopen(path, "r");
    if (fp == NULL)
    {
        printf("打開文件失敗\n");
        return;
    }
    // 字符緩沖區 , 每次讀一個字符串 , 都會緩存到字符數組中
    char buffer[1024];
    while (fgets(buffer, 1024, fp)) {
        printf("%s", buffer);
    }

    // 關閉文件流
    fclose(fp);

/*寫入文本文件*/
void writeTextFile() {
    char* path = "E:\\document\\write.txt";

    char* content = "如果 愛情是一場花火 ,一閃即逝的花火,我也要去追求\n如果 愛情是一場花火 ,一閃即逝的花火,我也要去追求\n";

    // 打開文件
    /*
        打開只寫文件,若文件存在則文件長度清為0,即該文件內容會消失。若文件不存在則建立該文件。
    */
    FILE* fp = fopen(path, "w");
    if (fp == NULL)
    {
        printf("打開文件失敗\n");
        return;
    }
    // 寫入文件
    fputs(content, fp);

    // 關閉文件流
    fclose(fp);
}
}

首先使用fopen函數得到一個文件指針 , 操作符r為讀取文件流 , 構建了一個buffer數據緩沖區 , 通過fgets函數循環讀取文件數據 , fclose函數關閉文件流 。在操作文件IO的時候 , 最重要的函數 , 莫過于fopen函數了 , 首先我們來看一下fopen函數的定義:

_ACRTIMP FILE* __cdecl fopen(
    _In_z_ char const* _FileName,
    _In_z_ char const* _Mode
    );

我們發現fopen函數 , 需要傳入文件全路徑名稱 , 還有一個_Mode , 這個是文件操作模式 , C語言中文件操作主要依靠操作模式來辨別是輸入流還是輸出流的 。
下面列舉一些常用的操作模式:

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

r 打開只讀文件,該文件必須存在。

r+ 打開可讀寫的文件,該文件必須存在。

w 打開只寫文件,若文件存在則文件長度清為0,即該文件內容會消失。若文件不存在則建立該文件。

w+ 打開可讀寫文件,若文件存在則文件長度清為零,即該文件內容會消失。若文件不存在則建立該文件。

a 以附加的方式打開只寫文件。若文件不存在,則會建立該文件,如果文件存在,寫入的數據會被加到文件尾,即文件原先的內容會被保留。

a+ 以附加方式打開可讀寫的文件。若文件不存在,則會建立該文件,如果文件存在,寫入的數據會被加到文件尾后,即文件原先的內容會被保留。

值得注意的是 , 上述操作模式是針對文本文件的 , 如果要操作二進制文件 , 則需要在上述操作符后面加上b , 如rb,wb,ab , 等等 。

不論是文本文件的操作還是字符文件的操作 , 都是 , 打開文件 , 創建緩沖區 , 讀寫文件 。

二進制文件讀寫

/*讀寫二進制文件 -- 復制文件*/
void fileCopy() {
    char* currentPath = "E:\\android_pdf\\研磨設計模式.pdf";
    char* destPath = "E:\\android_pdf\\研磨設計模式_new.pdf";

    // 打開文件
    FILE* currentFile_P = fopen(currentPath, "rb");
    FILE* destFile_P = fopen(destPath, "wb");

    // 先讀取再寫入
    int buffer[1024]; // 數據緩沖區
    int len; // 每次讀取數據的長度
    while ((len = fread(buffer,sizeof(int),1024,currentFile_P)) != EOF)
    {
        // 將緩沖區里的內容寫入到文件中
        fwrite(buffer, sizeof(int), len, destFile_P);
    }

    // 關閉流
    fclose(destFile_P);
    fclose(currentFile_P);
}

讀寫二進制和讀寫文本文件沒多少區別 , 最大的區別就是fopen函數中的模式的不同 , 文本文件是r,w , 二進制文件是rb,wb

了解了文件IO的基本操作 , 我們使用文件IO流寫一個加密解密的小程序。我們知道 , 所有的文件都是以二進制存儲的 , 我們看的文本文件, 圖片文件 , 視頻文件 , 都是以二進制存儲在磁盤上的 , 那么 , 我們可以將文件讀取出來 , 進行二進制運算 , 就可以將文件加密解密了 。下面我們通過^異或運算來進行文件的加密解密 , 異或運算的規則如下:

0 ^ 1 得 1
1 ^ 1 得 0
0 ^ 0 得 0
1 ^ 0 得 1

相同為0 不同為1 , 例如 , 我們將4這個數加密 , 異或的數是5 , 下面我們來看看運算:

4的二進制是:0100
5的二進制是:0101
異或運算結果(加密):4 ^ 5  == 0001    
異或運算結果(解密): 0001 ^ 0101 == 0100   
由上述可見 , ^一次為加密 , 再^一次就是解密

代碼示例如下:

文件加密

/*加密文件*/
void encryptFile() {

    // 待加密文件路徑
    char* normal_path = "E:\\poto\\xj.jpg";
    // 加密后文件路徑
    char* encrypt_path = "E:\\poto\\xj_encrypt.jpg";

    //打開文件
    FILE* normal_fp = fopen(normal_path, "rb");
    FILE* encrypt_fp = fopen(encrypt_path, "wb");
    // 讀文件
    int buffer;
    while ((buffer = fgetc(normal_fp)) != EOF) {
        // 寫入文件
        fputc(buffer ^ 8, encrypt_fp);
    }

    printf("文件加密成功\n");

    // 關閉流
    fclose(encrypt_fp);
    fclose(normal_fp);
}

文件解密

/*文件解密*/
void decryptFile() {
    // 加密文件路徑
    char* encrypt_path = "E:\\poto\\xj_encrypt.jpg";
    // 解密文件路徑
    char* decrypt_path = "E:\\poto\\xj_deencrypt.jpg";

    // 打開文件
    FILE* encrypt_fp = fopen(encrypt_path, "rb");
    FILE* decrypt_fp = fopen(decrypt_path, "wb");

    // 讀取文件
    int buffer;
    while ((buffer = fgetc(encrypt_fp)) != EOF) {
        // 寫文件
        fputc(buffer ^ 8, decrypt_fp);
    }

    printf("文件解密成功\n");

    // 關閉流
    fclose(decrypt_fp);
    fclose(encrypt_fp);
}

了解了文件加密的原理 , 我們也可以推導出其他形式的加密 , 如帶密碼的文件加密解密 , 混合文件加密解密等等 。

不知不覺C語言基礎系列已經寫了快十篇了 , 也快告一段落了 , 有了這些基礎知識 , 我們就可以去分析分析jni.h頭文件了 , 下一個系列是jni開發系列 , 我們學C語言就是為了能和java打交道 , 那么下個系列我們就來學習C與java的橋梁 , jni (Java Native Interface)技術 。

Android程序員學C系列:
C語言基礎及指針①
C語言基礎及指針②之指針內存分析
C語言基礎及指針③函數與二級指針
C語言基礎及指針④函數指針
C語言基礎及指針⑤動態內存分配
C語言基礎及指針⑥字符操作
C語言基礎及指針⑦結構體與指針
C語言基礎及指針⑧文件IO
C語言基礎及指針⑨聯合體與枚舉
C語言基礎及指針⑩預編譯及jni.h分析

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

推薦閱讀更多精彩內容

  • 接續上篇C語言基礎及指針⑧文件IO 在上篇中 , 我們初步了解了C語言的IO操作 , 編寫IO操作的大致流程: 文...
    逝我閱讀 1,961評論 1 5
  • 一、溫故而知新 1. 內存不夠怎么辦 內存簡單分配策略的問題地址空間不隔離內存使用效率低程序運行的地址不確定 關于...
    SeanCST閱讀 7,857評論 0 27
  • 指針是C語言中廣泛使用的一種數據類型。 運用指針編程是C語言最主要的風格之一。利用指針變量可以表示各種數據結構; ...
    朱森閱讀 3,464評論 3 44
  • 這些就是網站 openstudy
    趙禾禾閱讀 304評論 0 0
  • 今天學習了《論語 學而篇》的第二段,有子曰:“其為人也孝弟,而好犯上者,鮮矣;不好犯上而好作亂者,未之有也。...
    冷香丸子閱讀 223評論 0 0