數據結構day7——文件IO

一、標準 IO 的起源與概念

標準 IO(Standard Input/Output)是由 Dennis Ritchie 在 1975 年設計的一套 IO 庫,后來成為 C 語言的標準組成部分,并被 ANSI C 所采納。它是對底層文件 IO 的封裝,提供了更便捷、可移植的文件操作接口。

核心特點:

  • 設備抽象:將輸入輸出設備抽象為文件操作
    • 標準輸入設備:默認是鍵盤(/dev/input
    • 標準輸出設備:默認是顯示器
  • 跨平臺性:任何支持標準 C 的系統都可使用
  • 緩沖機制:在用戶程序和文件 IO 之間加入緩沖區,減少系統調用次數,提高效率

在 Linux 系統中,一切皆文件,IO 操作本質上都是對文件的操作。標準 IO 作為 C 語言標準庫的一部分,為文件操作提供了統一接口。

二、文件的基本概念

1. 文件的作用

文件是 Linux 系統中存儲數據(包括普通數據和指令)的基本單位,是數據持久化的載體。

2. Linux 文件類型(7 種)

  • d:目錄文件
  • -:普通文件
  • l:鏈接文件(link)
  • p:管道文件(pipe)
  • s:套接字文件(socket)
  • c:字符設備文件
  • b:塊設備文件

可通過ls -l命令查看文件類型,第一個字符即表示文件類型。

3. 文件內容分類

  • 文本文件:由 ASCII 字符組成,可直接閱讀
  • 二進制文件:由二進制數據組成,通常需要特定程序解析

三、IO 的分類

1. 標準 IO

  • 是 ANSI C 設計的一組封裝了文件 IO 的庫函數
  • 頭文件:stdio.h(位于/usr/include/stdio.h
  • 實現方式:stdio.hstdio.clibc.so(動態庫,位于/usr/lib
  • 特點:帶緩沖機制,可移植性好

2. 文件 IO

  • 屬于系統調用,是底層操作接口
  • 特點:無緩沖,直接與內核交互,效率高但使用復雜

四、頭文件引用方式

  • #include <stdio.h>:引用系統庫函數頭文件

    • 搜索路徑:系統默認路徑(如/usr/include/
  • #include "xxx.h":引用用戶自定義頭文件

    • 搜索路徑:當前目錄

五、流(Stream)的概念

流是數據從文件流入和流出所體現的字節序列,在標準 IO 中用FILE*指針表示(稱為流對象或文件流指針)。

1. 流的分類

  • 二進制流:由二進制數據組成的流
  • 文本流:由 ASCII 碼數據組成的流

2. 標準流

C 語言默認打開三個標準流:

  • stdin:標準輸入流(對應鍵盤)
  • stdout:標準輸出流(對應顯示器)
  • stderr:標準錯誤流(對應顯示器)

六、緩沖區機制

標準 IO 的一大特點是采用緩沖機制,目的是減少系統調用,提高效率。

1. 緩沖區類型

  • 行緩沖(1KB)

    • 應用場景:主要用于終端交互(如stdout
    • 刷新條件:遇到\n、緩沖區滿、程序正常結束、fflush()強制刷新
  • 全緩沖(4KB)

    • 應用場景:主要用于普通文件操作
    • 刷新條件:緩沖區滿、程序正常結束、fflush()強制刷新
  • 無緩沖(0KB)

    • 應用場景:主要用于錯誤處理(如stderr
    • 特點:數據直接輸出,不經過緩沖

2. 緩沖區操作函數

  • fflush(FILE *stream):強制刷新緩沖區

七、標準 IO 常用函數

1. 文件打開與關閉

  • fopen():打開文件并建立流

    FILE *fopen(const char *path, const char *mode);
    
    ?
    • mode參數:
      • r:只讀(文件不存在則報錯)
      • r+:讀寫(文件不存在則報錯)
      • w:只寫(文件不存在則創建,存在則清空)
      • w+:讀寫(文件不存在則創建,存在則清空)
      • a:追加寫(文件不存在則創建)
      • a+:追加讀寫(文件不存在則創建)
  • fclose():關閉文件流

    int fclose(FILE *stream);
    

2. 字符操作函數

  • fgetc(FILE *stream):從流中讀取一個字符
  • fputc(int c, FILE *stream):向流中寫入一個字符
  • getchar():從標準輸入讀取一個字符(fgetc(stdin)的宏定義)
  • putchar(int c):向標準輸出寫入一個字符(fputc(c, stdout)的宏定義)

示例:實現簡單的輸入輸出循環

while(1)fputc(fgetc(stdin), stdout);

3. 行操作函數

  • fgets(char *s, int size, FILE *stream):從流中讀取一行數據

    char *fgets(char *s, int size, FILE *stream);
    
    ?
    • 最多讀取size-1個字符,自動添加\0
    • 遇到\n會停止讀取,且\n會被包含在結果中
  • fputs(const char *s, FILE *stream):向流中寫入一行數據

    int fputs(const char *s, FILE *stream);
    
  • gets()/puts():與fgets()/fputs()類似,但gets()沒有緩沖區大小限制,存在安全隱患

4. 塊操作函數(二進制操作)

  • fread():從流中讀取指定大小的數據塊

    size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
    
  • fwrite():向流中寫入指定大小的數據塊

    size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
    

示例:結構體讀寫

struct person {char name[20];int age;char sex;char addr[100];
};struct person p = {"Tom", 20, 'M', "Beijing"};
fwrite(&p, sizeof(struct person), 1, fp);

5. 文件定位函數

  • fseek():移動文件指針

    int fseek(FILE *stream, long offset, int whence);
    
    ?
    • whence參數:
      • SEEK_SET:從文件開頭
      • SEEK_CUR:從當前位置
      • SEEK_END:從文件末尾
  • ftell():獲取當前文件指針位置

    long ftell(FILE *stream);
    
  • rewind():將文件指針移到開頭(等效于fseek(stream, 0L, SEEK_SET)

    void rewind(FILE *stream);
    

6. 其他常用函數

  • printf()/scanf():格式化輸入輸出
  • sprintf():將格式化數據寫入字符串
  • feof():判斷文件是否到達末尾
  • ferror():檢測流是否出錯
  • clearerr():清除流出錯標記

八、標準 IO 操作流程

  1. 打開文件:使用fopen()獲取文件流指針(FILE*
  2. 讀寫操作:根據需求選擇合適的 IO 函數(字符、行、塊操作)
  3. 關閉文件:使用fclose()關閉文件流,釋放資源

九、實踐練習

1. 實現簡易cat程序

#include <stdio.h>int main(int argc, char *argv[]) {FILE *fp;int c;if (argc != 2) {fprintf(stderr, "Usage: %s filename\n", argv[0]);return 1;}fp = fopen(argv[1], "r");if (fp == NULL) {fprintf(stderr, "Cannot open file %s\n", argv[1]);return 1;}while ((c = fgetc(fp)) != EOF) {fputc(c, stdout);}fclose(fp);return 0;
}

2. 實現文件拷貝功能

#include <stdio.h>
#include <stdlib.h>#define BUFFER_SIZE 1024int main(int argc, char *argv[]) {FILE *src, *dest;char buffer[BUFFER_SIZE];size_t n;if (argc != 3) {fprintf(stderr, "Usage: %s source destination\n", argv[0]);return 1;}src = fopen(argv[1], "rb");if (src == NULL) {fprintf(stderr, "Cannot open source file %s\n", argv[1]);return 1;}dest = fopen(argv[2], "wb");if (dest == NULL) {fprintf(stderr, "Cannot open destination file %s\n", argv[2]);fclose(src);return 1;}while ((n = fread(buffer, 1, BUFFER_SIZE, src)) > 0) {fwrite(buffer, 1, n, dest);}fclose(src);fclose(dest);return 0;
}

十、man 手冊的使用

man 手冊是查詢函數和命令的重要工具,分為不同章節:

  • man 1 xxx:查看命令幫助
  • man 2 xxx:查看系統調用函數
  • man 3 xxx:查看標準庫函數

例如:

  • man 3 fopen:查看 fopen 函數的詳細說明
  • man 3 printf:查看 printf 函數的用法

總結

標準 IO 是 C 語言中處理文件操作的重要接口,通過緩沖機制提高了 IO 效率,同時提供了豐富的函數族滿足不同場景的需求。掌握標準 IO 的使用,對于 C 語言程序開發至關重要。從基本的字符讀寫到復雜的文件定位,標準 IO 都提供了簡潔而強大的解決方案,是每個 C 程序員必須掌握的基礎知識。

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

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

相關文章

6.Docker部署ES+kibana

部署ES&#xff08;Elasticsearch&#xff09;kibana 1.ES暴露的端口很多 2.ES十分消耗內存 3.ES的數據一般需要掛載出去&#xff0c;放在安全目錄&#xff08;掛載) elastic 前往官方手冊 1.下載運行elasticsearch的 docker run -d --name elasticsearch --net somenet…

使用mysqldump對mysql數據庫進行備份

目錄 1軟件說明 2語法格式 3備份流程 3.1只備份指定數據庫中表和數據 3.1.1準備目錄 3.1.2備份db1數據庫里面的所有表信息 3.1.3還原備份 3.2備份數據庫結構 3.2.1備份db1數據庫的結構和數據 3.2.2還原數據庫 3.3備份所有數據庫 3.3.1備份數據庫 3.3.2還原數據庫 1…

vue3路由跳轉打開新頁面

Vue3 路由跳轉打開新頁面的方法 在 Vue3 中&#xff0c;有幾種方法可以實現路由跳轉時打開新頁面&#xff1a; 1. 使用 router.resolve 方法 import { useRouter } from vue-routerconst router useRouter()const openNewPage (path) > {const resolved router.resolv…

SeaTunnel 社區 2 項目中選“開源之夏 2025”,探索高階數據集成能力!

Apache SeaTunnel 社區在“開源之夏 2025”中再傳捷報&#xff0c;共有兩個項目成功入選&#xff0c;聚焦于 Flink CDC schema 支持與元數據管理的生態擴展方向&#xff0c;體現出 SeaTunnel 在實時數據集成和平臺化能力構建上的深入布局。 中選項目與學生如下&#xff1a; 《…

Neo4j無法建立到 localhost:7474 服務器的連接出現404錯誤

一、確認中文路徑問題&#xff08;核心原因&#xff09; 安裝路徑包含中文&#xff0c;可能導致 Windows 命令行或 Neo4j 解析路徑時出錯。 解決方法&#xff1a; 重新安裝 Neo4j 到英文路徑&#xff08;推薦&#xff09;&#xff1a; 將 Neo4j 解壓或安裝到不含中文的目錄&a…

鋰離子電池均衡拓撲綜述

鋰離子電池均衡拓撲綜述 一、引言 鋰離子電池因其高能量密度、長循環壽命等優點&#xff0c;在電動汽車、儲能系統等領域得到了廣泛應用。然而&#xff0c;電池組在使用過程中&#xff0c;由于電池個體差異、充放電管理等因素&#xff0c;會出現荷電狀態&#xff08;SOC&…

[面試] 手寫題-淺拷貝,深拷貝

淺拷貝 // 淺拷貝 function shallow(obj) {const newObj {}for (const key in obj) {// 保證 key 不是原型的屬性if (obj.hasOwnProperty(key)) {newObj[key] obj[key]}}return newObj }深拷貝 遞歸 O(n^2) // 深拷貝 function deepClone(obj {}) {// 如果傳入的是 null&am…

BehaviorTree.ROS2安裝記錄

坑比庫&#xff0c; 首先 git clone https://github.com/BehaviorTree/BehaviorTree.ROS2.git 依賴 git clone https://github.com/PickNikRobotics/cpp_polyfills.git git clone https://github.com/PickNikRobotics/RSL.git git clone https://github.com/PickNikRobotics/…

Vue基礎(19)_Vue內置指令

我們學過的vue內置指令&#xff1a; v-bind&#xff1a;單向綁定解析表達式&#xff0c;可簡寫為&#xff1a;:xxx v-model&#xff1a;雙向數據綁定 v-for&#xff1a;遍歷數組/對象/字符串 v-on&#xff1a;綁定事件監聽&#xff0c;可簡寫為 v-if&#xff1a;條件渲染(動態控…

排列組合初步

什么是排列組合 排列組合是計數問題&#xff0c;順序不同且值相同算兩種方案是排列&#xff0c;順序不同且值相同算一種方案是組合。 暴力枚舉方案能算出方案數&#xff0c;太耗時&#xff0c;運用加法原理和乘法原理可降低時間復雜度。先將原問題拆解成子問題&#xff0c;根…

SQL調優方案對比與最佳實踐

問題背景介紹 在大型互聯網或企業級應用中&#xff0c;數據庫往往成為系統性能的瓶頸。隨著數據量和并發量的增長&#xff0c;單一的 SQL 查詢可能出現響應遲緩、鎖等待、全表掃描等性能問題。為保證系統的穩定性和用戶體驗&#xff0c;需要對 SQL 查詢做深入的調優。常見的調…

Terraform Helm:微服務基礎設施即代碼

&#x1f680; Terraform & Helm&#xff1a;微服務基礎設施即代碼 &#x1f4da; 目錄 &#x1f680; Terraform & Helm&#xff1a;微服務基礎設施即代碼1. 引言 &#x1f680;2. 環境與依賴 &#x1f9f0;3. 架構示意 &#x1f3d7;?4. Terraform 定義云資源 &…

清理 Docker 緩存占用

Docker 緩存主要包括未使用的鏡像、容器、卷和網絡等資源。清理緩存可以提高磁盤空間&#xff0c;線上升級次數比較多的話&#xff0c;服務器中Docker緩存會非常嚴重&#xff0c;做下清理瘦身會有意想不到的效果 清理未使用的鏡像 運行以下命令刪除未被任何容器引用的鏡像&…

深入解析NumPy的核心函數np.array()

深入解析NumPy的核心函數np.array NumPy與np.array()簡介NumPy的重要性np.array()的作用 np.array()函數的詳細參數object參數dtype參數copy參數order參數subok參數ndmin參數like參數 np.array()函數的使用示例創建基本的一維和二維數組創建具有特定數據類型的數組創建多維數組…

定時器的設計

定時器 定時器原理如何理解定時器定時器數據結構選取定時器觸發方式 定時器的實現 定時器原理 如何理解定時器 定時器在日常通常被描述為組織大量延時任務的模塊&#xff0c;其實從字面意思去理解的話&#xff0c;他就是去處理延時任務的&#xff0c;那么什么是延時任務呢&am…

大模型-分布式論文一瞥

1分離式架構 1.1 DistServe DistServe: Disaggregating Prefill and Decoding for Goodput-optimized Large Language Model Serving DistServe: Disaggregating Prefill and Decoding for Goodput-optimized Large Language Model Serving 講的是一個將prefill和decoding分…

02.SpringBoot常用Utils工具類詳解

文章目錄 1. BeanUtils詳解1.1 什么是BeanUtils&#xff1f;1.2 主要的BeanUtils實現1.2.1 Spring BeanUtils1.2.2 Apache Commons BeanUtils1.2.3 其他實現 1.3 Spring BeanUtils詳細使用1.3.1 基本用法1.3.2 指定忽略屬性1.3.3 批量拷貝&#xff08;列表轉換&#xff09; 1.4…

Golang快速開發框架——項目立項與系統配置讀取組件viper(一)

Golang快速開發框架——項目立項與系統配置讀取組件viper&#xff08;一&#xff09; 背景 知識分享之Golang篇是我在日常使用Golang時學習到的各種各樣的知識的記錄&#xff0c;將其整理出來以文章的形式分享給大家&#xff0c;來進行共同學習。歡迎大家進行持續關注。 知識分…

打造可觀測的 iOS CICD 流程:調試、追蹤與質量保障全記錄

隨著iOS項目復雜度增加&#xff0c;團隊越來越依賴自動化構建、自動化測試等CI/CD流程來保證產品質量。但CI/CD環境下&#xff0c;很多線下調試手段無法直接使用&#xff0c;比如&#xff1a; 無法手動連真機跑Instruments測試包只在分發后才能拿到崩潰模擬器上表現和真機不一…

C++11中 <cinttypes>的入門與精通

文章目錄 一、<cinttypes> 是什么1. 固定寬度的整數類型2. 整數操作函數3. 格式化輸入輸出宏 二、深入理解 <cinttypes>1. 固定寬度整數類型的使用2. 整數操作函數的使用3. 格式化輸入輸出宏的使用 三、實踐和技巧1. 使用固定寬度整數類型的最佳實踐2. 使用整數操作…