C語言文件操作入門

本節重點

  • 理解文件的形式與基本概念
  • 二進制文件與文本文件
  • 文件的打開與關閉
  • 文件讀寫函數、
  • 文件緩沖區

正文開始---------------------------------------------------------------------------------------------------------------------

一、為什么使用文件

程序運行時數據存儲在內存中(如變量、數組),但程序結束后內存會被操作系統回收,數據隨之丟失,用戶配置、日志記錄、程序狀態等數據需跨會話保存,文件是操作系統提供的標準持久化方案,通過文件存儲,C 程序能夠突破內存限制,實現數據的長期保存和跨會話共享,是構建健壯應用程序的基礎能力。

也就是說數據保存在內存之中容易丟失,我們可以通過文件操作將數據保存在文件也就是磁盤或硬盤之中。

二、什么是文件

在計算機領域,文件是存儲數據的核心單位,用于將信息以特定格式保存在物理存儲設備(如硬盤、SSD)中。

在Windows中通過可視化操作界面,文件的存在形式是這樣的:

而在Linux操作系統中,通過命令行操作文件的存在形式是這樣的:

2.1 程序文件

程序文件是包含機器語言指令(二進制代碼)或解釋型語言代碼的文件,可被操作系統識別并執行從而實現特定的功能。

程序文件包括源程序文件(后綴為.c),目標文件(windows環境后綴為.obj),可執行文件(Windows環境后綴為.exe)。

2.2 數據文件

文件的內容不一定是程序,而是程序運行時讀寫的數據,比如程序運行需要從中讀取數據的文件,或者輸出內容的文件。

在這里,我們主要討論的是數據文件。

在之前我們所處理的數據的輸入輸出都是以終端為對象,即從終端的鍵盤輸入數據(主要通過scanf 函數),運行結果顯示到顯示器上(主要通過 printf 函數)。

其實有時候我們可以把信息輸出到磁盤上,當需要的時候再從磁盤上把數據讀取到內存中使用,這里處理的就是磁盤上的文件。

2.3、文件名

文件名要有一個唯一的文件標識,以便用戶識別和引用。

文件名包含3部分:文件路徑+文件主干+文件后綴,例如:

D:\code\new_code\code.exe

為了方便起見,文件標識符常被稱為文件名

四、二進制文件與文本文件

根據數據的組織形式,數據文件被稱為文本文件或者二進制文件。

數據在內存中以二進制的形式存儲,如果不加轉換就輸出到外存的文件中,就是二進制文件。如果要求在外存上以ASCLL碼的形式存儲,則需要在存儲前轉換,以ASCLL碼的形式存儲的文件就是文本文件。

一個數據在文件中是怎么存儲的呢?

字符一律按ASCLL碼的形式存儲,數值型數據既可以用ASCLL碼形式存儲也可以以二進制形式存儲。

例如,一個數值型數據10000以ASCLL碼存儲時一共有5個字符分別為1、0、0、0、0共占用5個字節,而以二進制形式存儲時占4個字節。

四、文件的打開與關閉

4.1 流和標準流

4.1.1 流

在編程中,“流”(Stream)是一種抽象的數據處理模型,用于逐步傳輸或處理數據,而無需一次性將整個數據加載到內存中。它類似于現實世界中的“水流”,數據像水流一樣按順序流動,程序可以按需讀取或寫入數據片段。

C程序針對文件、畫面、鍵盤等的數據的輸入輸出操作都是通過流實現的。

4.1.2 標準流

在編程中,“標準流”(Standard Streams)是操作系統或運行時環境預定義的三個默認數據流,用于程序與外界(如終端、文件或其他程序)進行交互。它們是:

  1. stdin? -標準輸入流,在大多數情況下從鍵盤輸入,scanf函數就是從標準輸入流中讀取數據
  2. stdout-標準輸出流,大多數環境中輸出到顯示器界面,printf函數就是將信息輸出到標準輸出流中
  3. stderror-標準錯誤流,大多數環境中輸出到顯示器界面。

當我們的程序啟動,或者說進程創建時,操作系統會為我們的程序自動分配三個標準流并默認連接到終端設備(顯示器、鍵盤)。

stdin、stdout、stderror三個流的類型都是FILE*,通常稱為文件指針,在C語言中就是通過文件指針來維護流的各種操作的

4.2 文件指針

當我們打開一個文件時,為了方便我們對被打開文件的進一步管理和維護,內存中就會開辟一個相應的“文件信息區”用來存放被打開文件的相關信息(如文件的名字,狀態以及文件當前的位置等等文件屬性)。這些信息是保存在一個結構體變量中的,也就是說這個“文件信息區”就是一個結構體,該結構體的類型是由系統聲明的,取名為FILE。

例如,vs2013編譯環境提供的stdio.h頭文件中有以下的文件類型聲明:

struct _iobuf {char *_ptr;int _cnt;char *_base;int _flag;int file;int _charbuf;int bufsiz;char *_tmpfname;};
typedef struct _iobuf FILE;

每當打開一個文件時,系統就會開辟內存空間創建一個FILE結構體來管理該文件的相關屬性和信息,使用者不必關心其細節。

為了將每個文件與所對應的“文件休信息區”(FILE)關聯起來,就引出了文件指針(FILE*)的概念。通過使文件指針指向某個文件的“文件信息區”(本質是一個結構體變量),通過該文件信息區中的信息就能找到并管理該文件。

也就是說,通過文件指針變量就能間接找到與它關聯的文件。

4.3 文件的打開與關閉

文件在讀寫之前首先應該打開文件,在使用結束后關閉文件。本質上就是保證打開文件后系統就會創建對應的“文件信息區”來方便用戶對文件進行管理與維護,關閉文件目的是釋放相應的內存空間,不然過多無效的“文件信息區”會占用內存,嚴重時會導致內存泄漏。

在編寫程序的時候,在打開文件的同時,都會返回一個FILE* 類型的指針變量指向該文件,也相當于建立了指針與文件的關系。

ANSIC規定使用fopen函數來打開文件,fclose來關閉文件:

//打開文件
FILE* fopen(const char* filename,const char* mode);//關閉文件
int fclose(FILE* stream);

mode參數表示文件的打開方式,下面都是文件的打開模式:

模式描述讀權限寫權限追加模式文件不存在時文件存在時初始位置
r只讀模式(文本文件)????失敗(返回?NULL保留內容,從文件開頭讀取文件開頭
w只寫模式(文本文件,覆蓋原有內容????創建新文件清空文件內容文件開頭
a追加模式(文本文件,寫入內容到文件末尾)?????創建新文件保留內容,寫入位置在文件末尾文件末尾
r+讀寫模式(文本文件,不截斷文件?????失敗保留內容,從文件開頭讀寫文件開頭
w+讀寫模式(文本文件,覆蓋原有內容?????創建新文件清空文件內容文件開頭
a+讀寫追加模式(文本文件,寫入到文件末尾,可讀取整個文件)??????創建新文件保留內容,寫入位置在文件末尾文件末尾(讀從開頭)
rb只讀模式(二進制文件)????失敗保留內容,從文件開頭讀取文件開頭
wb只寫模式(二進制文件,覆蓋原有內容????創建新文件清空文件內容文件開頭
ab追加模式(二進制文件,寫入內容到文件末尾)?????創建新文件保留內容,寫入位置在文件末尾文件末尾
r+b讀寫模式(二進制文件,不截斷文件?????失敗保留內容,從文件開頭讀寫文件開頭
w+b讀寫模式(二進制文件,覆蓋原有內容?????創建新文件清空文件內容文件開頭
a+b讀寫追加模式(二進制文件,寫入到文件末尾,可讀取整個文件)??????創建新文件保留內容,寫入位置在文件末尾文件末尾(讀從開頭)
x獨占創建模式(僅當文件不存在時創建,失敗返回?NULL??/????創建新文件失敗(文件已存在)文件開頭

實例代碼:

#include<stdio.h>int main()
{FILE* pf=fopen("text.txt","w");if(pf==NULL){//文件打卡失敗perror("fopen");return 0;}const char* txt="hello world!!";fputs(txt,pf);fclose(pf);return 0;
}

五、文件的順序讀寫

5.1? 字符讀寫

fgetc?

  • 功能:從文件中讀取單個字符
  • 參數:FILE* stream(文件指針)
  • 返回值:成功返回字符的int值,失敗或文件結束返回EOF

fputc

  • 功能:向文件中寫入單個字符
  • 參數:int c(字符),FILE* stream(文件指針)
  • 返回值:?成功返回寫入的字符,失敗返回EOF

5.2? 字符串讀寫

fgets

  • 功能:從文件中讀取一行字符串(直到遇到換行符或指定長度)
  • 參數:char* s(自定義緩沖區),int size(最大長度),FILE* stream(文件指針)
  • 返回值:成功返回緩沖區的指針,失敗或文件結束返回NULL

fputs

  • 功能:向指定文件中寫入一行字符串
  • 參數:const char* s(字符串),FILE* stream
  • 返回值:成功返回非負值,失敗返回EOF

5.3? 格式化讀寫

fscanf

  • 功能:按指定格式從文件中讀取數據
  • 參數:FILE* stream,格式化字符串,變量地址列表
  • 返回值:成功匹配并賦值的參數個數,失敗返回EOF

fprintf

  • 功能:按指定格式向文件中寫入數據
  • 參數:FILE* stream,格式化字符串,變量列表
  • 返回值:成功返回寫入的字符數,失敗返回負數

5.4? 塊讀寫(二進制模式)

fread

  • 功能:從文件中讀取二進制數據塊
  • 參數:void* ptr(緩沖區),size_t size(每個元素大小),size_t nmemb(要讀取的元素數量),FILE* stream。

  • 返回值:成功讀取的元素數量。

fwrite

  • 功能:向文件寫入二進制數據塊。
  • 參數:void* ptr(要寫入的數據的指針),size_t size(每個元素大小)size_t nmemb(要寫入的元素的數量)FILE *stream

  • 返回值:成功寫入的元素數量

六、文件的隨機讀寫?

文件的隨機讀寫允許程序直接跳轉到文件的任意位置進行讀寫操作,無需按順序訪問。

fseek

  • 功能:移動文件指針到指定位置
  • 參數:FILE* stream(文件指針),long offset(偏移量字節) ,int origin(基準位置)
  • 返回值:成功返回0,失敗返回非0值

ftell

  • 功能:返回文件指針相對于起始位置的偏移量
  • 參數:FILE* stream
  • 返回值: 成功返回long類型的偏移量

rewind

  • 功能:將文件指針重置到文件開頭
  • 參數:FILE* stream
  • 返回值: 無

七、文件緩沖區

在之后的學習中我們會了解到,其實C語言中文件的各類讀寫函數其實底層都封裝了系統調用接口read,write來向操作系統發出各類操作指令,而系統調用是一個復雜的概念它涉及到操作系統對內存空間的各類調度與管理,如果C語言中的文件函數直接訪問文件或磁盤中的數據,頻繁地進行讀取和寫入操作,就意味著系統調用接口的頻繁調用加重CPU的負擔,減低I/O的效率

為了避免這個問題,我們引入了文件緩沖區的概念,它通過先將程序數據先放入緩沖區中,通過刷新機制將多次小數據量的讀寫合并為少量大塊操作,減少直接訪問磁盤的次數,顯著提升I/O效率,避免頻繁的系統調用。

?寫個代碼驗證一下:

#include<stdio.h>
#include<windows.h>
int main()
{FILE*pf = fopen("test.txt", "w");fputs("abcdef", pf);//先將代碼放在輸出緩沖區printf("睡眠10秒已經寫數據了,打開test.txt?件,發現?件沒有內容\n");Sleep(10000);printf("刷新緩沖區\n");fflush(pf);//刷新緩沖區時,才將輸出緩沖區的數據寫到?件(磁盤)//注:fflush 在?版本的VS上不能使?了printf("再睡眠10秒-此時,再次打開test.txt?件,?件有內容了\n");Sleep(10000);fclose(pf);//注:fclose在關閉?件的時候,也會刷新緩沖區pf = NULL;return 0
}

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

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

相關文章

Doris:聯邦認證

LDAP? 接入第三方 LDAP 服務為 Doris 提供驗證登錄和組授權服務。 LDAP 驗證登錄? LDAP 驗證登錄指的是接入 LDAP 服務的密碼驗證來補充 Doris 的驗證登錄。Doris 優先使用 LDAP 驗證用戶密碼&#xff0c;如果 LDAP 服務中不存在該用戶則繼續使用 Doris 驗證密碼&#xff…

stm32第六天繼電器

一&#xff1a;繼電器 1.繼電器的工作原理 繼電器是一個電控開關&#xff0c;工作原理基于電磁感應&#xff0c;繼電器包括一個電磁線圈和一組觸點。常用于控制高電流或高電壓的電路&#xff0c;例如自動控制原理&#xff0c;電力系統和自動化設備中&#xff0c;由于可靠性和電…

Vue渲染函數 - render 函數

文章目錄 Vue渲染函數 - render 函數1. 什么是 render 函數2、頁面展示過程3、render 函數的參數4. 如何使用&#xff08;1&#xff09;基本渲染&#xff08;2&#xff09;傳遞屬性和事件&#xff08;3&#xff09;條件渲染 5. render 函數的實際使用6.View Design 組件中的使用…

單片機自學總結

自從工作以來&#xff0c;一直努力耕耘單片機&#xff0c;至今&#xff0c;頗有收獲。從51單片機&#xff0c;PIC單片機&#xff0c;直到STM32&#xff0c;以及RTOS和Linux&#xff0c;幾乎天天在搞:51單片機&#xff0c;STM8S207單片機&#xff0c;PY32F003單片機&#xff0c;…

go回調函數的使用

在Go語言中&#xff0c;回調函數可以有參數&#xff0c;也可以沒有參數。它們的定義和使用方式略有不同&#xff0c;但本質上都是將函數作為參數傳遞給另一個函數&#xff0c;并在適當的時候調用它。以下是帶參數和不帶參數的回調函數的示例和說明。 1. 不帶參數的回調函數 不…

在 Ubuntu 中配置 NFS 共享服務的完整指南

前言 網絡文件系統&#xff08;NFS&#xff09;作為 Linux 系統間實現文件共享的標準協議&#xff0c;在分布式計算和容器化部署場景中具有重要作用。本文將詳細演示如何在 Ubuntu 系統上配置 NFS 服務端與客戶端&#xff0c;并實現可靠的持久化掛載。 一、環境準備 系統要求…

TypeScript Symbols 深度解析:在 Vue3 中的高級應用實踐

一、Symbols 核心特性解析 1.1 什么是 Symbol&#xff1f; Symbol 是 ES6 引入的原始數據類型&#xff0c;表示唯一且不可變的值&#xff0c;主要解決對象屬性名沖突問題。在 TypeScript 中&#xff0c;我們通過 symbol 類型獲得完整的類型支持&#xff1a; const SERIAL_KE…

無需刷機、root,暢享原生安卓的絲滑體驗。

Apex Launcher 是一款歷史悠久的 Android 桌面啟動器&#xff0c;誕生于 Android 系統早期&#xff08;Android 4.0 時代&#xff09;。當時&#xff0c;Android 系統的默認界面被認為較為簡陋&#xff0c;無法滿足一些追求個性化和高效操作的用戶需求。因此&#xff0c;許多開…

Visual Studio Code安裝配置優化全攻略:打造高效開發環境

目錄 一、背景與意義 二、安裝與配置基礎 2.1 下載與安裝 2.2 核心配置目錄 三、深度優化配置指南 3.1 主題與界面優化 3.2 必裝效率插件&#xff08;精選TOP10&#xff09; 3.3 性能優化設置 四、實戰案例&#xff1a;前端開發環境配置 4.1 項目初始化 4.2 調試配置…

味覺傳送器E-Taste:開啟虛擬世界的味覺之門

味覺傳送器E-Taste&#xff1a;開啟虛擬世界的味覺之門 一、發明背景與動機 隨著虛擬現實&#xff08;VR&#xff09;和增強現實&#xff08;AR&#xff09;技術的飛速發展&#xff0c;人們在虛擬世界中的沉浸感不斷提升&#xff0c;視覺和聽覺體驗已經取得了顯著的突破。然而…

判斷質數與合數

判斷質數與合數的邏輯很相似&#xff0c;都是判斷一個屬除了1和它本身&#xff0c;能不能被其他數整除。 其他數包括質數與合數&#xff0c;合數能表示能質數的乘積&#xff0c;因此問題就轉化為&#xff1a;一個數能不能被除了1和它本身之外的其他質數整除。 質數2&#xff…

在Spring Boot項目中接入DeepSeek深度求索,感覺笨笨的呢

文章目錄 引言1. 什么是DeepSeek&#xff1f;2. 準備工作2.1 注冊DeepSeek賬號 3.實戰演示3.1 application增加DS配置3.2 編寫service3.3 編寫controller3.4 編寫前端界面chat.html3.5 測試 總結 引言 在當今快速發展的數據驅動時代&#xff0c;企業越來越重視數據的價值。為了…

Cursor在內網環境配置自定義DeepSeek API

關鍵字 Cursor、DeepSeek、API配置、內網代理、HTTP/2 背景環境 使用Cursor集成環境開發程序。但是我使用公司的內網并不能使用cursor自帶的模型&#xff0c;于是我就想使用DeepSeek官方的API服務。 環境&#xff1a;Windows 11系統 解決過程 網絡檢測 首先進行環境檢測&am…

RabbitMQ 集群降配

這里寫自定義目錄標題 摘要檢查狀態1. 檢查 RabbitMQ 服務狀態2. 檢查 RabbitMQ 端口監聽3. 檢查 RabbitMQ 管理插件是否啟用4. 檢查開機自啟狀態5. 確認集群高可用性6. 檢查使用該集群的服務是否做了斷開重連 實操1. 負載均衡配置2. 逐個節點降配&#xff08;滾動操作&#xf…

設計模式之外觀模式:原理、實現與應用

引言 外觀模式&#xff08;Facade Pattern&#xff09;是一種結構型設計模式&#xff0c;它通過提供一個統一的接口來簡化復雜系統的使用。外觀模式隱藏了系統的復雜性&#xff0c;使得客戶端可以通過一個簡單的接口與系統交互。本文將深入探討外觀模式的原理、實現方式以及實…

進行交通流預測,使用KAN+Transformer模型

理論基礎 KAN&#xff08;Knowledge Augmented Network&#xff09; KAN 是一種知識增強網絡&#xff0c;其核心思想是將先驗知識融入到神經網絡中&#xff0c;以此提升模型的性能與泛化能力。在交通流預測領域&#xff0c;先驗知識可以是交通規則、歷史交通模式等。通過把這…

TF中 Arg 節點

TF中 Arg 節點 在 TensorFlow 的計算圖中&#xff0c;_Arg 節點&#xff08;Argument Node&#xff09;表示函數的輸入參數&#xff0c;是計算圖中負責接收外部輸入數據的節點。它的名字來源于“Argument”&#xff08;參數&#xff09;&#xff0c;直接對應函數調用時傳入的張…

Educational Codeforces Round 176 (Rated for Div. 2)

A.To Zero 簽到題 void solve() { int n,k;cin>>n>>k;int k2k/2*2;int k1(k2<k)?k:k-1;int cnt0;if(n%21){n-k1;cnt;cnt(n/k2)(n%k2!0);}else {cnt(n/k2)(n%k2!0);}cout<<cnt<<endl;}B.Array Recoloring 手推一下可以發現&#xff0c;答案其實就…

Kubernetes的Service詳解

一、Service介紹 在 kubernetes 中&#xff0c; pod 是應用程序的載體&#xff0c;我們可以通過 pod 的 ip 來訪問應用程序&#xff0c;但是 pod 的 ip 地址不是固定的&#xff0c;這也就意味著不方便直接采用pod 的 ip 對服務進行訪問。 為了解決這個問題&#xff0c;kuberne…

基于Nvidia Jetson Nano邊緣計算設備使用TensorRT部署YOLOv8模型實現目標檢測推理

0、背景 最近拿到一臺邊緣計算設備&#xff0c;在部署YOLO模型的過程中遇到一些問題&#xff0c;特此記錄。 設備介紹信息&#xff1a;NVIDIA Jetson Orin Nano T201Developer Kit 開發套件 開發者套件&#xff1a;Jetson Orin Nano T201 8GB開發套件 使用指南文檔&#x…