C標準輸出入函數庫 與 作業系統.

Slides:



Advertisements
Similar presentations
电子成绩单项目实现.
Advertisements

第1单元 操作系统概论 第一节 绪论 操作系统定义.
行程(process).
第九章 字串 (String).
補充: Input from a text file
基于操作系统的编程复习 张玉宏
雷 霆 战 机 By—谷恩轩&余万全.
第11章 输入输出流类.
第 5 章 文件I/O操作.
C程序设计 第10章 文 件 主讲教师: 鲁 萍 西安建筑科技大学 理学院.
第十三章 文件.
第8章 字元與字串處理 8-1 C語言的字元檢查函數 8-2 C語言的字串 8-3 字串的輸入與輸出 8-4 指標與字串
南京天石软件技术有限公司 陈锺 (QQ: Solaris 10 C编程 南京天石软件技术有限公司 陈锺 (QQ:
複習 struct score_Type{ int chinese,english; }; struct my_Type{
C File System.
高级语言程序设计 主讲人:陈玉华.
chapter 1-Introduction
计算概论 第二十一讲 文件操作 北京大学信息学院.
程序设计II 第三讲 字符串处理.
函數 授課:ANT 日期:2011/3/28.
第7章 Linux环境编程.
第10章 文件操作.
第十一章 文件 文件概述 文件操作 文件操作实例 本章小结 作业: 练习:
计算概论 第十八讲 C语言高级编程 结构与习题课 北京大学信息学院.
第10章 文件操作.
C 程式設計— 檔案處理 台大資訊工程學系 資訊系統訓練班.
Function.
11.1 文件的基本概念 11.2 文件的打开与关闭 11.3 文件的顺序读写 11.4 文件的随机读写 11.5 文件检测
第十二章 文件 12.1 C文件概述 文件:存储在外部介质上数据的集合,是操作系统数据管理的单位 文件分类 按文件的逻辑结构: 按存储介质:
fp=fopen("CD2.dat","wb"); fwrite(&min,8,1,fp); fclose(fp);
第4章 MATLAB文件操作 4.1 文件的打开与关闭 4.2 文件的读写操作 4.3 数据文件定位.
檔案 將資料存入磁碟或由磁碟取出資料的方式, 稱為檔案存取處理。 C語言的檔案處理 C++語言的檔案處理.
程式設計 博碩文化出版發行.
Linux操作系统分析 中国科学技术大学计算机系 陈香兰(0512- )
作業系統實習課(四) -檔案管理- 實驗室:720A 助教:鄧執中.
第九章 文件 程序数据标准输入输出设备 程序数据文件 数据流和文件 文件的打开和关闭 文件读写函数.
File(檔案處理) 學習目標:開檔、讀檔、更新檔與關閉檔案.
THE C PROGRAMMING LANGUAGE
第10章 文件操作.
字符串和字符数组 字符串的输入和输出 字符串的基本操作
第10章 檔案與資料夾處理 10-1 C語言的檔案輸入與輸出 10-2 文字檔案的讀寫 10-3 二進位檔案的讀寫
ACM程序员大赛讲座 _____C语言程序设计要点 讲授人:王敬华.
Linux 文件操作——系统调用和标准 IO 库
第5章 文件.
第9章 文件操作 文件 使用文件的目的 操作系统管理数据的基本单位 存储在外存储器上的数据的集合
計數式重複敘述 for 迴圈 P
研讨课4 文件操作.
C++ 程式設計 基礎篇 張啟中 Chang Chi-Chung.
一、文件的基本概念 第十三章 文 件 所谓“文件”是指一组相关数据的有序集合。 这个数据集有一
第7章 输入/输出流 文件和I/O流概述 标准I/O流的对象及其成员函数 文件流.
第3章 變數、算術運算、 數學函數及輸入輸出.
函式庫補充資料.
指標
C程序设计.
File Input and Output Chap. 11: 施威銘的書 Chap. 7: K&R.
本节内容 文件读写 视频提供:昆山爱达人信息技术有限公司.
第二章 类型、对象、运算符和表达式.
C程序设计.
授课老师:龚涛 信息科学与技术学院 2016年3月 教材:《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
挑戰C++程式語言 ──第9章 函數.
第13章 文 件.
C 程式設計— 檔案處理 台大資訊工程學系 資訊系統訓練班.
实验二:添加Linux系统调用及熟悉常见系统调用
結構、檔案處理(Structure, File)
1.4WIN32中的宽字符.
作業一: 安裝Linux於btrfs上 中正大學 作業系統實驗室 指導教授:羅習五
第七章 文件 7.1 文件的基本概念 7.2 文件类型指针 7.3 文件的打开与关闭 7.4 文件的读/写 7.5 文件的随机读/写
C 程式設計— 字元與字串 台大資訊工程學系 資訊系統訓練班.
2018 Operating Systems 作業系統實習 助教:林欣穎 實驗室:720A Lab2.
C语言程序设计 第13章 文件操作.
Presentation transcript:

C標準輸出入函數庫 與 作業系統

開啟檔案、讀寫檔案

fopen() #include <stdio.h> int main(int argc, char **argv) { FILE* file; file = fopen("./tmp", "w"); fprintf(file, "this is a tmp file\n"); return 0; }

fopen() #include <stdio.h> FILE *fopen(const char *path, const char *mode); FILE *fdopen(int fd, const char *mode); 回傳值是FILE這個資料型別 初始化FILE只能用stdio定義的函數操作,如:fopen、fdopen fdopen可以將上一個章節教的file descriptor轉換為FILE物件

fopen的mode參數 fopen可以接多種參數,常用的參數如下,修飾參數接在參數之後 參數 代表意義 r 開啟檔案以供讀取(檔案要原本就存在) w 開啟檔案以供寫入。如果原本就有這個檔案,原先檔案的內容會被清除。原本沒有這個檔案,系統自動建立此檔案。 a 開啟檔案以供寫入,所寫入的資料附加於原檔案之後。原本沒有這個檔案,系統自動建立此檔案。 r+ 和「r」一樣,但打開的檔案可供「讀、寫」 w+ 和「w」一樣,但打開的檔案可供「讀、寫」 a+ 和「a」一樣,但打開的檔案可供「讀、寫」 某些作業系統還提供b這個mode(例如:rb),代表binary,但UNIX並不特別區分「字」與「二進位碼」,因此我們可以忽略b這個mode(如果加上「b」UNIX,也會忽略這個mode)。

stdin、stdout、stderr 在UNIX內,一啟動程式作業系統就會自動幫我們開啟三個「檔 案」,分別是標準輸入、標準輸出及標準錯誤輸出,這三個檔案 對應的FILE物件如下 FILE物件 「通常」的設備 標準輸入 stdin 鍵盤 標準輸出 stdout 螢幕 標準錯誤輸出 stderr

fprintf printf將「格式化」後的字串印到標準輸出(通常是螢幕) fprintf將「格式化」後的字串印到檔案 #include <stdio.h> int printf(const char * restrict format, ...) int fprintf(FILE * restrict stream, const char * restrict format, ...) int sprintf(char* restrict str, const char * restrict format, ...) printf將「格式化」後的字串印到標準輸出(通常是螢幕) fprintf將「格式化」後的字串印到檔案 sprintf將「格式化」後的字串印到「記憶體」

Example: fprintf & mode #include <stdio.h> int main(int argc, char **argv) { FILE* file; file = fopen("./tmp", argv[1]); fprintf(file, "this_is_a_tmp_file\n");; fclose(file); return 0; }

執行結果 $./write+read2 a+ $less ./tmp this_is_a_tmp_file (END) 使用完檔案後,用fclose關閉檔 案

檔案位置(position) int fseek(FILE *stream, long offset, int whence); long ftell(FILE *stream); 這二個函數分別會設定(fseek)和回傳檔案位置(position),特別要注意 的是fseek並不會回傳目前的檔案位置,因此要得到檔案位置必須使用ftell 和lseek很像,fseek提供三個選項,分別是SEEK_SET, SEEK_CUR, SEEK_END 成功回傳0,失敗回傳-1

append + fseek #include <stdio.h> int main() { FILE *stream; char buf[100]; int ret; stream = fopen("./tmp", "a+"); ret = fseek(stream, 2, SEEK_SET); fread(buf, 100, 1, stream); printf(buf); printf("\nreturn value = %d\n", ret); fprintf(stream, "append?"); printf("position = %d\n", ftell(stream)); return 0; }

結果 $./append+fseek this_is_a_tmp_file append? return value = 0 position = 85 $less ./tmp 使用a, a+打開的stream也可以使 用fseek,回傳值為0 fseek可以改變「讀取位置」, fseek會改變讀取的資料的位置 但實際上「寫入的資料會放在檔 案的最後面」

C函數庫的buffer #include <stdio.h> int fflush(FILE *stream); 系統內部有二個重要的buffer,分別位於C函數庫(如果我們使 用的是stdio相關的函數),另一個位於核心(Linux kernel), 當執行fflush時會將C函數庫內所有被buffer的資料寫到OS。 如果想要確保OS的buffer資料也寫入到硬碟則需要使用fsync,但 我們只有FILE物件沒有file descriptor。此時可以使用int fileno(FILE *stream) 。

設定buffer的大小 #include <stdio.h> void setbuf(FILE *stream, char *buf); void setbuffer(FILE *stream, char *buf, size_t size); void setlinebuf(FILE *stream); int setvbuf(FILE *stream, char *buf, int mode, size_t size);

以setvbuf為例 int setvbuf(FILE *stream, char *buf, int mode, size_t size); 依照mode的指示設定stream,並且以buf為buffer,該buffer的大小為size setvbuf必須在「真正使用」stream前使用才會有效果 請記得,使用setvbuf前應該要有這樣的動作:buf=malloc(size); mode有三種選項 _IONBF unbuffered,所有寫入到stream的物件立即寫入到stream _IOLBF line buffered,當遇到換行符號(\n)才將該「字串」寫到stream _IOFBF fully buffered,當buffer滿了,才將這些物件寫入stream

setvbuf #include <stdio.h> sscanf(argv[1], "%d", &bufSize); #include <stdlib.h> buf = (char*)malloc(bufSize); setvbuf(stream, buf, _IOFBF, bufSize); int main(int argc, char **argv) for (i=0; i<dataSize; i++) { fwrite("d", 1, 1, stream); FILE* stream; return 0; int bufSize; } int dataSize = 10000000; char *buf; int i; stream = fopen("./tmp", "w+");

結果 bufsize real user sys 100 10.666s 0.104s 6.248s 1000 0.725s 0.308s 10000 0.239s 0.016s

讀寫檔案 以fread為例,從stream讀取nmemb筆資料,每筆資料的大小為size這麼大, 到ptr所指向的buffer #include <stdio.h> size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); 以fread為例,從stream讀取nmemb筆資料,每筆資料的大小為size這麼大, 到ptr所指向的buffer 以fwrite為例, 從ptr所指向的buffer的資料,寫出到stream。共寫出nmemb 筆資料,每筆資料的大小為size這麼大 fread及fwrite的回傳值都是「讀取幾筆資料」,不是讀取多少個字元

Errors 及 EOF int feof(FILE *stream); int ferror(FILE *stream); void clearerr(FILE *stream); 以fread為例,不管是發生錯誤或者讀到檔案結尾,回傳值都小於 預期(例如小於要寫出的資料量)。那我們要怎樣區分EOF和 Error? feof、ferror可以分別測出到底是檔案結尾或者是錯誤 測試完畢以後呼叫clearerr清除該「錯誤標示」

feof #include <stdio.h> if (ferror(stream)) printf("error\n"); int main() { if (feof(stream)) FILE *stream; printf("EOF\n"); char buf[5000]; } int ret; return 0; stream = fopen("./tmp", "a+"); ret=fread(buf, 10, 500, stream); printf("ret = %d\n", ret); if(ret!=1) {

寬字串(wide string, i18n)

strlen.c #include <stdio.h> #include <wchar.h> #include <string.h> int main(int argc, char **argv) { char *str = "中文"; printf("%d\n", (int)strlen(str)); return 0; }

執行結果 $ ./strlen 6 『中文』是二個字,但strlen卻 告訴我們『中文』是三個字 這是因為中文是unicode編碼非 ASCII編碼

wcslen.c #include <stdio.h> #include <wchar.h> #include <string.h> int main(int argc, char **argv) { wchar_t* wstr = L"中文"; printf("%d\n", (int)wcslen(wstr)); return 0; }

執行結果 $./wcslen 2 wchar_t* wstr = L“中文”;宣告 wstr是寬字元字串 使用wcslen(寬字元版本的 strlen)就可以正確的判斷出 字串的長度

fwide() int fwide (FILE *stream, int mode) mode為0時,回傳stream目前的讀寫狀態。大於0切換為讀寫寬字 串,小於0切換為讀寫一般字串

寬字元的讀取及寫入 #include <wchar.h> wchar_t *fgetws(wchar_t *ws, int n, FILE *stream); int fputws(const wchar_t *ws, FILE *stream); 寬字元(萬國碼,unicode)幾乎都定義在<wchar.h> 例如fgetws可以從stream中讀取一個寬字元字串

tmp file char *tempnam(const char *dir, const char *pfx); FILE *tmpfile(void); char *tmpnam(char *s); char *mktemp(char *template);

以mktemp為例 char *mktemp(char *template); 在系統中建立一個「唯一的檔案」 template的格式為「最後6個字母必須是XXXXXX(一定要大寫)」 XXXXXX會被替換成一個「唯一的字串」,確保這個檔案的檔名 在系統中是唯一 通常用來製造暫存檔案

mktemp #include <stdio.h> #include <stdlib.h> #include <errno.h> int main() { FILE* stream; char tmpStr[] = "./shiwulo_XXXXXX"; mktemp(tmpStr); printf("%s\n", tmpStr); stream = fopen(tmpStr, “w+”); /*權限為600,只有owner才可以讀寫*/ if (stream == NULL) perror("error: "); fputs("hello\0", stdout); return 0; }