linux程式設計——檔案操作(第三章)

來源:互聯網
上載者:User

標籤:

上篇是檔案操作(第三章上),文章中的代碼在檔案操作(代碼下載)。

3.6 格式化輸出和輸入3.6.1 printf、fprintf和sprintf函數printf函數能夠對各種不同類型的參數進行格式化編排和輸出。每個參數在輸出資料流中的表示形式由格式化參數format控制,它是一個包含需要輸出的一般字元和轉換控制符代碼的字串。
#include <stdio.h>
int printf(const char* format, ...);
int sprintf(char* s, const char* format, ...);
int fprintf(FILE* stream, const char* format, ...);
printf函數把自己的輸出送到標準輸出,fprintf函數把自己的輸出送到一個指定的檔案流。sprintf函數把自己的輸出和一個結尾孔字元寫到作為參數傳遞過來的字串s裡。
printf("some numbers: %d,%d and %d\n", 1, 2, 3);
%d,%i     輸出十進位整數
%o,%x    輸出八進位或者十六進位整數
%c        輸出一個字元
%s        輸出一個字串
%d        輸出一個浮點數
%e        輸出科學計數法格式的浮點數
%g        輸出(雙精確度)浮點數
printf函數返回一個整數一表明它輸出的字元個數。
sprintf的返回值裡並沒有算上結尾的那個Null 字元。
3.6.2 scanf、fscanf和sscanf函數scanf函數從一個檔案流裡讀取資料,並 把資料值放到以指標參數形式傳遞過來的地址處的變數中
#include <stdio.h>
int scanf(const char *format, ...);
int fscanf(FILE* stream, const char* format,...);
int sscanf(const char* s, const char* format, ..);
scanf系列函數中,那些一般字元是用於指定在輸入資料裡必須出現的字元。例如:
int num;
scanf("hello %d", &num);
這個scanf調用只有在標準輸入中接下來的五個字元匹配"hello"的情況下才會成功。
使用%c控制符從輸入中讀取一個字元,它不會跳過起始的空白字元。
使用%s控制符來掃描字串,則會跳過起始的空白字元,並且會在字串裡出現的第一個空白字元處停下來,所以最好使用它來讀取單詞而不是一般意義上的字串。
使用 %[]控制符讀取由一個字元集和中的字元構成的字串。格式字串%[A-Z]將讀取一個由大寫字母構成的字串。如果字元集中第一個字元是^,將表示將讀取一個不屬於由該字元集和中的字元構成的字串。因此,讀取一個其中帶空格的字串,並且在遇到第一個逗號時停止,可以使用%[^,]。
給定下面輸入行:
hello, 1234, 5.678, X, string to the end of the line
char s[256];
int n;
float f;
char c;
scanf("hello,%d,%g,%c,%[^\n], &n,&f,&c,s);
scanf函數的返回值是它成功讀取的資料項目個數,如果在讀取第一個資料項目時失敗了,它的返回值將是0。如果在匹配第一個資料項目之前就已經到達了輸入的尾,就返回EOF。
3.6.3 其他流函數stdio函數庫裡還有一些其他的函數使用流參數或標準流stdin、stdout和stderr,如下所示:
fgetpos:獲得檔案流的當前(讀寫)位置
fsetpos:設定檔案流的當前(讀寫)位置
編寫copy_stdio.c程式
運行這個程式,發現雖然 不如底層資料庫複寫版本塊(copy_block.c),但是比那個 系統調用每次複製一個字元的版本快很多(copy_system.c)。這是 因為stdio庫在FILE結構裡使用了一個內部緩衝區,只有在緩衝區時才進行底層系統調用
3.6.4 檔案流錯誤為了表明錯誤,許多stdio庫函數會返回一個超出範圍的值,比如null 指標或者EOF常數。此時,錯誤由外部變數errno指出:
#include <errno.h>
extern int errno;
因為許多函數都可能改變errno的值,它的值只有在函數調用失敗時才有意義。必須在函數調用失敗之後立刻對其進行檢查。
也可以通過檢查檔案流的狀態來確定是否發生了錯誤,或者是否到達了檔案尾。
#include <stdio.h>
int ferror(FILE* stream);
int feof(FILE* stream);
void clearerr(FILE* stream);
3.7 檔案和目錄的維護標準庫和系統調用為檔案和目錄的建立與維護提供了全面的支援。
3.7.1 chmod系統調用可以 通過chmod系統調用來改變檔案或目錄的存取權限。這構成了shell程式chmod的基礎。
該函數原型如下:
#include <sys/stat.h>
int chmod(const char* path, mode_t mode);
path參數指定的檔案被修改為具有mode參數給出的存取權限。參數mode的定義與open系統調用中的一樣,也是對所要求的存取權限進行按位OR操作。
3.7.2 chown系統調用超級使用者可以使用chown系統調用來改變一個檔案的屬主。
#include <sys/types.h>
#include <unistd.h>
int chown(const char *path, uid_t owner, gid_t group);
這個調用使用的是使用者ID和組ID的數字值(通過getuid和getgid調用獲得)和一個用於限定誰可以修改屬主的系統值。
3.7.3 unlink、link和symlink系統調用可以使用unlink系統調用來刪除一個檔案。
unlink系統調用刪除一個檔案的目錄項並減少它的連結數。它在成功時返回0,失敗時返回-1。函數原型如下:
#include <unistd.h>
int unlink(const char* path);
int link(const char *path1, const char *path2);
int symlink(const char *path1, const char *path2);
如果一個檔案的連結數減少到零,並且沒有進程開啟它,這個檔案就會被刪除。事實上,目錄項總是被立刻刪除,但檔案所佔用的空間要等到最後一個進程(如果有的話)關閉它之後才會被系統回收。rm程式使用的就是這個調用。
link系統調用將建立一個指向已有檔案path1的新連結。新目錄項由path2給出。
3.7.4 mkdir和rmdir系統調用可以使用mkdir和rmdir系統調用來建立和刪除目錄
#include <sys/types.h>
#include <sys/stat.h>
int mkdir(const char* path, mode_t mode);
mkdir系統調用用於建立目錄,它相當於mkdir程式,mkdir調用將參數作為建立目錄的名字。
#include <unistd.h>
int rmdir(const char* path);
rmdir系統調用用於刪除目錄,但是只有在目錄為空白時才可以。
3.7.5 chdir系統調用和getcwd函數程式可以像使用者在檔案系統裡那樣瀏覽目錄,就像shell裡使用cd命令切換目錄一樣,程式使用的是chdir系統調用
#include <unistd.h>
int chdir(const char *path);
程式可以通過調用getcwd函數來確定自己的當前工作目錄。
#include <unistd.h>
char *getcwd(char *buf, size_t size);
getcwd函數把目前的目錄的名字寫到給定的緩衝區buf裡。
3.8    掃描目錄linux系統上一個常見的問題就是掃描目錄,也就是確定一個特定目錄下存放的檔案。在shell程式設計中,這很容易做到——只需要讓shell做一次運算式的萬用字元擴充。
與目錄操作有關的函數在dirent.h標頭檔中生命。它們使用一個名為DIR的結構作為目錄操作的基礎。被稱為目錄流的指向這個結構的指標被用來完成各種目錄操作。
3.8.1 opendir函數opendir函數的作用是開啟一個目錄並建立一個目錄流。
#include <sys/types.h>
#include <dirent.h>
DIR* opendir(const char* name);
3.8.2 readdir函數readdir函數返回一個指標,該指標指向的結構裡儲存著目錄流dirp中下一個目錄項的有關資料。
#include <sys/types.h>
#include <dirent.h>
struct dirent* readdir(DIR* dirp);
3.8.3 telldir函數telldir函數的返回值記錄著一個目錄流裡的當前位置。
#include <sys/types.h>
#include <dirent.h>
long int telldir(DIR* dirp);
3.8.4 seekdir函數seekdir函數的作用是設定目錄流dirp的目錄項指標,loc的值用來設定指標位置,它應該通過一個telldir調用獲得。
#include <sys/types.h>
#include <dirent.h>
void seekdir(DIR* dirp, long int loc);
3.8.5 closedir函數closedir函數關閉一個目錄流並釋放與之相關聯的資源。
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR* dirp);
編寫printdir.c程式,實現一個簡單的目錄列表功能。
3.10 /proc檔案系統linux將一切事物看作為檔案,硬體裝置在檔案系統中也有相應的條目。我們使用底層系統調用這樣一種特殊方式通過/dev目錄中的檔案訪問硬體。
linux提供了一個特殊的檔案系統procfs,它通常以 /proc目錄的形式呈現。該目錄中包含了許多特殊檔案用來對驅動程式和核心資訊進行更高層的訪問
例如/proc/cpuinfo給出的是cpu的詳細資料。
/proc/meminfo和/proc/version分別給出的是記憶體使用量情況和核心版本資訊。
/proc/net/socket檔案給出網路通訊端的使用統計
/proc目錄中以數字命名的子目錄用於提供正在啟動並執行程式的資訊。
每個進程都有一個唯一的標識符:一個在1-32000的數字。ps命令給出當前正在運行進程的列表。
3.11 進階主題3.11.1 fcntl系統調用fcntl系統調用對底層檔案描述符提供了更多的操作方法。
#include <fcntl.h>
int fcntl(int fildes, int cmd);
int fcntl(int fildes, int cmd, long arg);
3.11.2 mmap函數mmap(記憶體映射)函數的作用是建立一段可以被兩個或者更多個程式讀寫的記憶體。一個程式對它所做出的修改可以被其他程式看見。
mapp函數建立一個指向一段記憶體地區的指標,該記憶體地區與可以通過一個開啟的檔案描述符訪問的檔案的內容相關聯。
#include <sys/mman.h>
void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);
3.12 小結這章主要學習linux提供的直接存取檔案和裝置的方法,介紹建立在這些底層函數之上的庫函數是如何為程式設計問題提供靈活的解決方案的。


linux程式設計——檔案操作(第三章)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.