文件操作詳解(萬字長文)

C語言文件操作

  • 一、為什么使用文件?
  • 二、文件分類
  • 三、文件的打開和關閉
  • 四、文件的順序讀寫
    • 4.1fputc
    • 4.2fgetc
    • 4.3fputs
    • 4.4fgets
    • 4.5 fprintf
    • 4.6 fscanf
    • 4.7 fwrite
    • 4.8 fread
  • 五、文件的隨機讀寫
    • 5.1 fseek
    • 5.2 ftell和rewind
    • 六、文件讀取結束的判定
    • 七、文件緩沖區

一、為什么使用文件?

我們以創建變量舉例,假設我們創建一個整型變量b,并且我們將它初始化為100,這樣我們寫的數據是儲存在電腦的內存中的,然后我們退出程序,內存回收,數據就丟失了,等到再次運行程序的時候是看不到上一次程序的數據的。那我們能不能把它長久保存下來呢?這就需要用到文件,文件是保存在磁盤上的,使用磁盤(文件)來儲存數據我們就可以對數據進行持久化儲存。

二、文件分類

  • 程序文件:包括源程序文件(后綴為.c)目標文件(在windows環境下后綴為.obj)可執行程序(在windows環境下后綴為.exe)。
  • 數據文件:文件也不一定都是程序,也有可能文件中存放的是程序運行時讀寫的數據,這就是數據文件。

文件名:一個文件要有一個唯一的文件標識,以便用戶識別和引用。
文件名包含三個部分:文件路徑 + 文件名主干 + 文件后綴
例如:c:\code\test.c 中的c:\code\就是文件路徑,test就是文件名主干,.c就是文件后綴。

二進制文件和文本文件
根據數據的組織形式,數據被稱為二進制文件文本文件。
數據在內存中是以二進制的形式存儲的,如果它不加轉換的輸出到外存的文件中,就是二進制文件,如果要求在外存的基礎上以ASCll碼的形式存儲,這時候就需要在儲存前轉換,以ASCll碼形式儲存的文件就是文本文件

三、文件的打開和關閉

文件在讀之前需要先打開文件,這時候你就需要一枚鑰匙(fopen),在使用之后你還要關閉文件,這時候你需要一把鎖(fclose)。

這兩個函數都在#include <stdio.h>下,接下來我們來講解這兩個函數。
首先來看fopen的函數原型:

FILE* fopen(const char* filename,const char*mode);
//filename就是你要打開的文件名
//mode是你要以什么方式打開,像讀、寫等等

打開完成后fopen會返回一個FILE*類型的指針用于文件操作,如果打開失敗fopen會返回空指針(NULL),所以通常我們需要對fopen的返回值進行判斷。
關于文件的使用方式可以參照以下表格:

文件使用方式含義如果指定文件不存在
“r”(只讀)為了輸入數據,打開一個已經存在的文本文件出錯
“w”(只寫)為了輸出數據,打開一個文本文件建立一個新的文件
“a”(追加)像文本文件末尾添加數據建立一個新的文件
“rb”(只讀)為了輸入數據,打開一個二進制文件出錯
“wb”(只寫)為了輸出數據,打開一個二進制文件建立一個新的文件

等等還有很多種操作,這里小編只列舉了這幾種方式來進行解釋。
之后是fclose的函數原型

int fclose(FILE* stream);
//stream是指向文件的FILE*類型的指針

示例
首先我不創建text.c的文件:

#include<stdio.h>int main()
{FILE* pf;pf = fopen("text.c", "r");if (pf == NULL){printf("打開失敗");}else{printf("打開成功");}fclose(pf);pf = NULL;return 0;
}

結果:
在這里插入圖片描述
之后我再創建文件:
在這里插入圖片描述
結果:
在這里插入圖片描述

四、文件的順序讀寫

既然我們已經可以打開關閉文件了,那總要做點什么吧,比如說往文件里面寫一些數據,或者讀一些數據,這時候就需要用到我們的函數,首先介紹順序讀寫,之后介紹隨機讀寫。

函數名功能適用于
fgetc字符輸入函數所有輸入流
fputc字符輸出函數所有輸出流
fgets文本行輸入函數所有輸入流
fputs文本行輸出函數所有輸出流
fscanf格式化輸入函數所有輸入流
fprintf格式化輸出函數所有輸出流
fread二進制輸入文件輸入流
fwrite二進制輸出文件輸出流

4.1fputc

函數原型:
在這里插入圖片描述
這個函數的作用是向stream指向的文件中寫東西。
注意:fputc是向文件中寫數據,文件打開方式應該使用"w"
示例:

#include<stdio.h>int main()
{FILE* pf;pf = fopen("text.txt", "w");if (pf == NULL){perror("fopen");return 1;}//寫文件for (int i = 'a';i < 'z';i++){fputc(i, pf);}fclose(pf);pf = NULL;return 0;
}

程序執行前:
在這里插入圖片描述
程序執行后:
在這里插入圖片描述

4.2fgetc

函數原型:
在這里插入圖片描述
fgetc函數的作用是從文件中讀取數據,我們可以把讀取到的數據打印在屏幕上。

注意:此時是從文件中讀取數據是只讀的情況,所以文件打開方式應該選用“r”,當文件中的字符被逐個讀完之后沒有字符可讀,或者一開始就沒有字符可讀時,fgetc函數會返回EOF(-1),所以我們可以以EOF來判斷是否讀取結束。

示例

#include<stdio.h>int main()
{FILE* pf;pf = fopen("text.txt", "r");if (pf == NULL){perror("fopen");return 1;}//讀文件int c = 0;while ((c = fgetc(pf)) != EOF){printf("%c ", c);}fclose(pf);pf = NULL;return 0;
}

結果:
在這里插入圖片描述

4.3fputs

函數原型:
在這里插入圖片描述
注意:向文件中寫入字符串,打開文件方式用“w”

實例:

#include<stdio.h>int main()
{FILE* pf;pf = fopen("text.txt", "w");if (pf == NULL){perror("fopen");return 1;}//寫文件fputs("hello world\n", pf);fputs("hello new world\n",pf);fclose(pf);pf = NULL;return 0;
}

結果:
在這里插入圖片描述

4.4fgets

函數原型:
在這里插入圖片描述
示例:

#include<stdio.h>int main()
{FILE* pf;pf = fopen("text.txt", "r");if (pf == NULL){perror("fopen");return 1;}//讀文件char c[101];char s[101];fgets(c, 13, pf);fgets(s, 16, pf);printf("%s", c);printf("%s", s);fclose(pf);pf = NULL;return 0;
}

結果:
在這里插入圖片描述

使用fgets的注意事項:
1、當你要求它讀取8個字符的時候他其實會從文件中讀取7個字符剩下的那個字符空間他會用來儲存‘\0’。
2、不知道大家有沒有發現我的打印函數里面都沒有添加換行符,但打印出來卻換行了,這是因為fgets讀取到了文件行末尾的換行符。

4.5 fprintf

函數原型:
在這里插入圖片描述
首先函數的第一個參數是指向文件的FILE*指針,第二個參數是傳入數據的形式,像%d、%f這些。
示例:

#include<stdio.h>int main()
{FILE* pf;pf = fopen("text.txt", "w");if (pf == NULL){perror("fopen");return 1;}//寫文件fprintf(pf, "%d %lf %c", 100, 3.14, 'a');fclose(pf);pf = NULL;return 0;
}

結果:
在這里插入圖片描述

4.6 fscanf

函數原型:
在這里插入圖片描述
示例:

#include<stdio.h>int main()
{FILE* pf;pf = fopen("text.txt", "r");if (pf == NULL){perror("fopen");return 1;}int n;double d;char c;//讀文件fscanf(pf, "%d %lf %c", &n,&d,&c);printf("%d\n", n);printf("%f\n", d);printf("%c\n", c);fclose(pf);pf = NULL;return 0;
}

結果:
在這里插入圖片描述

4.7 fwrite

函數原型:
在這里插入圖片描述

其中ptr指針指向的是要傳文件數據的數組,size是一次傳送的字節大小,count是傳送的次數,stream是FILE*類型的指針。此時文件的打開方式應該是“wb”。

示例:

#include<stdio.h>int main()
{FILE* pf;pf = fopen("text.txt", "wb");if (pf == NULL){perror("fopen");return 1;}//寫文件int a[] = { 1,2,3 };fwrite(a,sizeof(a[0]),3,pf);fclose(pf);pf = NULL;return 0;
}

結果:
在這里插入圖片描述
當我們以二進制的形式存入數據的時候,它給出的結果我們已經識別不出來了,我們轉化為2進制再看一下:
在這里插入圖片描述
以二進制的方式打開我們發現的確儲存了1,2,3,而且是以16進制的形式儲存的和內存的儲存形式相同。

4.8 fread

函數原型:
在這里插入圖片描述

其中ptr指針指向的是要存放數據的數組,size是從文件讀取的字節大小,count是讀取的個數,stream是FILE*類型的指針。此時文件的打開方式應該是“rb”。

示例:

#include<stdio.h>int main()
{FILE* pf;pf = fopen("text.txt", "rb");if (pf == NULL){perror("fopen");return 1;}//讀文件int arr[4] = { 0 };for (int i = 0;i < 3;i++){fread(arr + i, sizeof(arr[0]), 1, pf);printf("%d ", arr[i]);}fclose(pf);pf = NULL;return 0;
}

結果:
在這里插入圖片描述

五、文件的隨機讀寫

5.1 fseek

函數原型:
在這里插入圖片描述
第一個參數是一個FILE*類型的指針,第二個參數是偏移量,第三個參數是參照系。那這個具體是什么意思呢?就是選擇一個參照系,比如我選擇文件開頭,然后偏移量選擇3,那就是從文件中第三個字符開始讀取的意思。

關于參照系這里有一個表格,它一共有三個取值:
在這里插入圖片描述
SEEK_SET:文件的開始位置
SEEK_CUR:光標的當前位置
SEEK_END:文件末尾位置

示例:

#include<stdio.h>int main()
{FILE* pf;pf = fopen("text.txt", "r");if (pf == NULL){perror("fopen");return 1;}//讀文件char arr[10];fseek(pf, -11, SEEK_END);arr[0] = fgetc(pf);fputc(arr[0], stdout);fclose(pf);pf = NULL;return 0;
}

結果:
在這里插入圖片描述
另外兩個origin取值也是相同的用法。

5.2 ftell和rewind

ftell的函數原型:
在這里插入圖片描述
它只有一個參數就是文件指針,它的作用是返回光標當前位置。

rewind的函數原型:
在這里插入圖片描述
它也只有一個參數就是文件指針,它的作用是讓光標回到文件的起始位置。

示例:

#include<stdio.h>int main()
{FILE* pf;pf = fopen("text.txt", "r");if (pf == NULL){perror("fopen");return 1;}//讀文件char arr[10];fseek(pf, -11, SEEK_END);arr[0] = fgetc(pf);fputc(arr[0], stdout);long int n = ftell(pf);printf("\n%ld\n", n);rewind(pf);n=ftell(pf);printf("%ld", n);fclose(pf);pf = NULL;return 0;
}

結果:
在這里插入圖片描述

六、文件讀取結束的判定

C語言中有一個函數是feof,它的作用是當文件讀取結束的時候,判斷讀取的原因是不是遇到文件尾而結束。
注意:在文件讀取的過程中不能用feof函數的返回值直接判斷文件是否結束。
它的函數原型:
在這里插入圖片描述
那如何判斷文件是否讀取結束呢?
對于文本文件
例如:fgetc判斷返回值是不是EOF,fgets判斷返回值是不是NULL。
對于二進制文件
二進制文件是否讀取結束,是判斷返回值是不是小于實際要讀的個數。
例如:fread判斷返回值是否小于實際要讀的個數。

示例:

#include<stdio.h>int main()
{FILE* pf;pf = fopen("text.txt", "r");if (pf == NULL){perror("fopen");return 1;}//讀文件int c;while ((c = fgetc(pf)) != EOF){putchar(c);}if (ferror(pf))//判斷是不是異常結束{printf("\nI/O error when reading");}else if (feof(pf))//判斷是不是正常結束{printf("\nEnd of file reached successfully");}fclose(pf);pf = NULL;return 0;
}

結果:
在這里插入圖片描述

七、文件緩沖區

ANSI C 標準是采用“緩沖文件系統”處理數據文件的,所謂緩沖文件系統是指系統自動地在內存中為程序中每一個正在使用的文件開辟一塊“文件緩沖區”。從內存向磁盤輸出數據會先送到內存中的緩沖區,裝滿緩沖區后才一起送到磁盤(文件)上。如果從磁盤向計算機讀入數據,則從磁盤文件中讀取數據輸入到內存緩沖區(充滿緩沖區),然后再從緩沖區逐個地將數據送到程序數據區(程序變量等)。緩沖區的大小根據C編譯系統決定的。

例如:
當我們輸入數據時,系統會開辟一個輸入緩沖區,假設這個緩沖區的大小是固定的,我們輸入數據時它會等到緩沖區被充滿后在一起送到磁盤上,輸出緩沖區也是這樣。這樣就大大解放了程序的空間和時間,使計算機能夠同時處理更多的事。
在這里插入圖片描述

總結
以上就是全部的今天博客內容,內容稍微有點多,讀者朋友可以點個關注,博主后續還會給大家帶來更多的優質內容~
另外,如果有什么問題,可以在評論區留言,博主看到后,會一一回復。
好了,讓我們下期博客再見!
(~ ̄▽ ̄)~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/72993.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/72993.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/72993.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于 JDBC 的后端與 MySQL 數據庫交互 javaweb

一、了解JDBC 二、添加MySQL的JDBC驅動包 三、使用JDBC連接數據庫應用&#x1f517; 3.1創建一個包 3.2 查找實例 3.3 修改添加刪除實例 四、封裝 &#x1f4e6; DBConnection.java MysqlUtil.java 測試使用一下 測試1 測試2 在后端開發中&#xff0c;與數據庫進行交…

貪心算法--

1.檸檬水找零 link:860. 檸檬水找零 - 力扣&#xff08;LeetCode&#xff09; code class Solution { public:bool lemonadeChange(vector<int>& bills) {// 貪心算法&#xff0c; 優先花出大面額bill&#xff0c; 盡可能保護小面額billint five 0, ten 0;// 不…

基于YOLO11深度學習的電瓶車進電梯檢測與語音提示系統【python源碼+Pyqt5界面+數據集+訓練代碼】

《------往期經典推薦------》 一、AI應用軟件開發實戰專欄【鏈接】 項目名稱項目名稱1.【人臉識別與管理系統開發】2.【車牌識別與自動收費管理系統開發】3.【手勢識別系統開發】4.【人臉面部活體檢測系統開發】5.【圖片風格快速遷移軟件開發】6.【人臉表表情識別系統】7.【…

github生成badges的方法

在Github頁面上生成類似下面這樣的badge的方法 你可以通過以下步驟在GitHub個人主頁的README中創建類似的技術棧徽章&#xff1a; 一、使用 Shields.io 生成徽章 Shields.io 是一個開源徽章生成工具&#xff0c;支持自定義文本、顏色、圖標等參數。 1. 基礎模板 https://…

vue3 二次封裝uni-ui中的組件,并且組件中有 v-model 的解決方法

在使用uniappvue3開發中&#xff0c; 使用了uni-ui的組件&#xff0c;但是我們也需要自定義組件&#xff0c;比如我要自定一個picker 的組件&#xff0c; 是在 uni-data-picker 組件的基礎上進行封裝的 父組件中的代碼 <classesselect :selectclass"selectclass"…

Spring Boot啟動流程及源碼實現深度解析

Spring Boot啟動流程及源碼實現深度解析 一、啟動流程概述 Spring Boot的啟動流程圍繞SpringApplication類展開&#xff0c;核心流程可分為以下幾個階段&#xff1a; 初始化階段&#xff1a;推斷應用類型&#xff0c;加載ApplicationContextInitializer和ApplicationListene…

爬蟲案例七Python協程爬取視頻

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 前言一、Python協程爬取視頻 前言 提示&#xff1a;這里可以添加本文要記錄的大概內容&#xff1a; 爬蟲案例七協程爬取視頻 提示&#xff1a;以下是本篇文章正文…

uni-app開發的App和H5嵌套封裝的App,以及原生App有什么區別

uni-app 開發的 App 和 H5 嵌套封裝的 App 是兩種不同的開發模式&#xff0c;雖然它們都可以實現跨平臺開發&#xff0c;但在技術實現、性能、功能支持等方面有顯著區別。以下是詳細對比&#xff1a; 1. uni-app 開發的 App uni-app 是一個基于 Vue.js 的跨平臺開發框架&#…

Python 爬蟲實戰案例 - 獲取拉勾網招聘職位信息

引言 拉勾網&#xff0c;作為互聯網招聘領域的佼佼者&#xff0c;匯聚了海量且多樣的職位招聘信息。這些信息涵蓋了從新興科技領域到傳統行業轉型所需的各類崗位&#xff0c;無論是初出茅廬的應屆生&#xff0c;還是經驗豐富的職場老手&#xff0c;都能在其中探尋到機遇。 對…

LM Studio 替換源的方式解決huggingface.co無法訪問的問題

安裝軟件完成之后&#xff0c;不要打開&#xff0c;打開了就直接關閉 在安裝目錄下&#xff0c;比如我安裝在E:\Program Files\LM Studio 下面三個文件中的huggingface.co全部替換為hf-mirror.com然后再打開即可。 E:\Program Files\LM Studio\resources\app\.webpack\rende…

【模擬CMOS集成電路設計】帶隙基準(Bandgap)設計與仿真(基于運放的電流模BGR)

【模擬CMOS集成電路設計】帶隙基準&#xff08;Bandgap&#xff09;設計與仿真 前言工程文件&部分參數計算過程&#xff0c;私聊~ 一、 設計指標指標分析&#xff1a; 二、 電路分析三、 仿真3.1仿真電路圖3.2仿真結果(1)運放增益(2)基準溫度系數仿真(3)瞬態啟動仿真(4)靜態…

微服務拆分-遠程調用

我們在查詢購物車列表的時候&#xff0c;它有一個需求&#xff0c;就是不僅僅要查出購物車當中的這些商品信息&#xff0c;同時還要去查到購物車當中這些商品的最新的價格和狀態信息&#xff0c;跟購物車當中的快照進行一個對比&#xff0c;從而去提醒用戶。 現在我們已經做了服…

機動車授權簽字人考試的報名條件是什么?

機動車授權簽字人考試的報名條件通常如下&#xff1a; 學歷職稱與工作經驗要求 中級職稱及以上&#xff1a;應具備中級及以上專業技術職稱&#xff0c;且從事相關檢驗檢測工作三年及以上。如果承檢車型有專項作業車、大型客車、校車和危險貨物運輸車等&#xff0c;若不是相關專…

智慧工廠監測信息系統:構筑安全的數字化未來

在現代工業的浪潮中&#xff0c;智慧工廠已成為推動生產效率和產品質量提升的關鍵力量。為了確保這一先進生產模式的穩健運行&#xff0c;智慧工廠監測信息系統應運而生&#xff0c;并通過一系列安全措施&#xff0c;為企業的數字化轉型保駕護航。 安全注冊&#xff0c;筑牢第…

P2P中NAT穿越方案(UDP/TCP)(轉)

轉自&#xff1a;P2P中NAT穿越方案&#xff08;UDP/TCP&#xff09;_udp反向鏈接-CSDN博客 同&#xff1a;P2P中NAT穿越方案&#xff08;UDP/TCP&#xff09; - 知乎 (zhihu.com) 本文介紹了傳統基于udp的打洞方式&#xff0c;更進一步闡述了tcp打洞的原理&#xff0c;是對于…

算法 之 樹形dp 樹的中心、重心

文章目錄 重心實踐題目小紅的陡峭值 在樹的算法中&#xff0c;求解樹的中心和重心是一類十分重要的算法 求解樹的重心 樹的重心的定義&#xff1a;重心是樹中的一個節點&#xff0c;如果將這個點刪除后&#xff0c;剩余各個連通塊中點數的最大值最小&#xff0c;那么這個節點…

游戲引擎學習第146天

音高變化使得對齊讀取變得不可能&#xff0c;我們可以支持循環聲音了。 我們今天的目標是完成之前一段時間所做的音頻代碼。這個項目并不依賴任何引擎或庫&#xff0c;而是一個教育項目&#xff0c;目的是展示從頭到尾運行一個游戲所需要的全部代碼。無論你對什么方面感興趣&a…

深入理解MySQL主從原理

導讀 高鵬&#xff08;網名八怪&#xff09;&#xff0c;《深入理解MySQL主從原理》系列文的作者。 本系列通過GTID、Event、主庫、從庫、案例分析&#xff0c;五大塊來詳細講解主從原理。 這篇文章重在學習筆記整理&#xff01; 在學習《深入理解MySQL主從原理》一書時&…

前端數據模擬利器 Mock.js 深度解析

前端數據模擬利器 Mock.js 深度解析 一、Mock.js 核心價值 1.1 為何需要數據模擬 前后端并行開發加速接口文檔驅動開發異常場景模擬測試演示環境數據構造 1.2 Mock.js 核心能力 // 典型數據生成示例 Mock.mock(/api/user, {"users|5-10": [{"id|1": 1…

Phi-4-multimodal:圖、文、音頻統一的多模態大模型架構、訓練方法、數據細節

Phi-4-Multimodal 是一種參數高效的多模態模型&#xff0c;通過 LoRA 適配器和模式特定路由器實現文本、視覺和語音/音頻的無縫集成。訓練過程包括多階段優化&#xff0c;確保在不同模式和任務上的性能&#xff0c;數據來源多樣&#xff0c;覆蓋高質量網絡和合成數據。它的設計…