日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

文件I/O实践(1) --基础API

發布時間:2025/3/17 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 文件I/O实践(1) --基础API 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

什么是I/O

輸入/輸出是內存和外設之間拷貝數據的過程:

? ?設備->內存:?輸入操作

? ?內存->設備:?輸出操作


?高級I/O:?ANSI?C提供的標準I/O庫函數成為高級I/O,?也稱為帶緩沖的I/O;

?低級I/O:?Linux?提供的系統調用,?通常也稱為不帶緩沖的I/O;

?

文件描述符

? 對于Linux內核而言,?所有的文件或設備都對應一個文件描述符(Linux的設計哲學:?一切皆文件),?這樣可以簡化系統編程的復雜程度;

? 當打開/創建一個文件的時候,?內核向進程返回一個文件描述符(是一個非負整數).?后續對文件的操作只需通過該文件描述符即可進行,?內核記錄有關這個打開文件的信息;

? 一個進程啟動時,?默認已經打開了3個文件,?標準輸入(0,?STDIN_FILENO),?標準輸出(1,?STDOUT_FILENO),?標準錯誤輸出(2,?STDERR_FILENO),?這些常量定義在unistd.h頭文件中;?

? 其中,?文件描述符基本上是與文件描述指針(FILE*)一一對應的,?如文件描述符0,1,2?對應?stdin,?stdout,?stderr;

?

文件指針與文件描述符的轉換

fileno:?將文件指針轉換成文件描述符

???????int?fileno(FILE?*stream);

fdopen:?將文件描述符轉換成文件指針

???????FILE?*fdopen(int?fd,?const?char?*mode);

//示例 int main() {cout << "fileno(stdin) = " << fileno(stdin) << endl;cout << "fileno(stdout) = " << fileno(stdout) << endl;cout << "fileno(stderr) = " << fileno(stderr) << endl;return 0; }

文件I/O?API

1.open

#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode);

參數:

? ?pathname:? 文件名,?可以包含[絕對/相對]路徑名;

? ?flags: 文件打開模式;

? ?mode: 用來指定對文件所有者,?文件用戶組以及系統中的其他用戶的訪問權限;

注意:?newMode?=?mode?&?~umask

?

flags常用值


//示例1 int main() {int fd = open("test.txt", O_RDONLY);if (fd == -1){cerr << "file open error, errno = " << errno <<"\nstrerror: " << strerror(errno) << endl;perror("perror");exit(EXIT_FAILURE);}cout << "file open success" << endl; } //示例2 inline void err_exit(std::string message) {perror(message.c_str());exit(EXIT_FAILURE); }int main() {umask(0000);int fd = open("test.txt", O_RDWR|O_CREAT|O_EXCL, 0666);if (fd == -1)err_exit("file open error");elsecout << "file descriptor = " << fd << endl; }

[附]

(1).?umask?API

? ?//改變umask值

? ?mode_t?umask(mode_t?mask);

(2).?ulimit?-a

? ?查看系統中的各種限制;

? ?其中-n:?查看一個進程所能夠打開的最大文件數

(3).?cat?/proc/sys/fs/file-max?

? ?查看一個系統能夠支持的最大打開文件數(該數與內存大小有關)


2.close

#include <unistd.h> int close(int fd);

關閉文件描述符,?使得文件描述符得以重新利用

?

3.read

ssize_t read(int fd, void *buf, size_t count);

返回值:

? 錯誤:?-1

? 到達文件尾:?0

? 成功:?返回從文件復制到規定緩沖區的字節數

?

4.wirte

ssize_t write(int fd, const void *buf, size_t count);

返回值:

? ?錯誤:?-1

? ?什么都沒做:?0

? ?成功:?返回成功寫入文件的字節數

?

注意:

? ?write返回大于0時,?并不代表buf的內容已經寫入到磁盤上的文件中了,?其僅僅代表buf中的數據已經copy到相應的內核緩沖區了.?要實現將緩沖區的內容真正”沖洗”到磁盤上的文件,?需要調用fsync函數;

? ? ?int?fsync(int?fd);

? ?其將內核緩沖區中尚未寫入磁盤的內容同步到文件系統中;

? ?其實在open調用的時候也可以指定同步選項:O_SYNC? O_SYNC?The?file?is?opened?for?synchronous?I/O.???Any??write(2)s??on??the??resulting??file??descriptor?will?block?the?calling?process?until?the?data?has?been?physically?written?to?the?underlying?hardware.

? ?write會等到將buf的內容真正的寫入到磁盤才真正返回;

//示例: 帶有O_SYNC選項 int main(int argc, char *argv[]) {if (argc < 3){cerr << "Usage : " << argv[0] << " src dest" << endl;exit(EXIT_FAILURE);}int infd = open(argv[1], O_RDONLY);if (infd == -1)err_exit("file O_RDONLY error");int outfd = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC|O_SYNC, 0666);if (outfd == -1)err_exit("file O_WRONLY error");char buf[1024];int readBytes, writeBytes;while ((readBytes = read(infd, buf, sizeof(buf))) > 0){writeBytes = write(outfd, buf, readBytes);cout << "readBytes = " << readBytes<< ", writeBytes = " << writeBytes << endl;} }

文件的隨機讀寫

5.lseek

對應于C庫函數中的fseek,?通過指定相對于當前位置,?末尾位置或開始位置的字節數來重定位currp:

off_t lseek(int fd, off_t offset, int whence);

返回值:?新的文件偏移值;

?

Whence取值:

SEEK_SET

? ?The?offset?is?set?to?offset?bytes.

SEEK_CUR

? ?The?offset?is?set?to?its?current?location?plus?offset?bytes.

SEEK_END

? ?The?offset?is?set?to?the?size?of?the?file?plus?offset?bytes.

//示例1 int main(int argc, char *argv[]) {int fd = open("test.txt", O_RDONLY);if (fd == -1)err_exit("open error");char buf[1024] = {0};int readBytes = read(fd, buf, 5);cout << "readBytes = " << readBytes << ", buf: " << buf << endl;int seekCount = lseek(fd, 0, SEEK_CUR);cout << "current offset = " << seekCount << endl; } //示例2: 產生空洞文件 int main(int argc, char *argv[]) {int fd = open("hole.txt", O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0666);if (fd == -1)err_exit("open error");if (write(fd, "ABCDE", 5) == -1)err_exit("first write error");//創建一個1G的文件if (lseek(fd, 1024*1024*1024, SEEK_CUR) == -1)err_exit("lseek error");if (write(fd, "Hello", 5) == -1)err_exit("second write error");close(fd); }

[附]

-查看hole.txt文件

? od?-c?hole.txt

??cat?-A?hole.txt

-查看該文件大小

??du?-h?hole.txt

??du?-b?hole.txt

??du?-k?hole.txt

??du?-m?hole.txt

?

目錄訪問

6.opendir

#include <sys/types.h>#include <dirent.h>DIR *opendir(const char *name);

返回值:

? ?成功: 返回目錄指針;

? ?失敗: 返回NULL;

?

7.readdir

struct dirent *readdir(DIR *dirp);

返回值:

? ?成功:?返回一個指向dirent結構的指針,?它包含指定目錄的下一個連接的細節;

? ?沒有更多連接時,?返回0;

struct dirent {ino_t d_ino; /* inode number */off_t d_off; /* not an offset; see NOTES */unsigned short d_reclen; /* length of this record */unsigned char d_type; /* type of file; not supportedby all filesystem types */char d_name[256]; /* filename */ };

8.closedir:?關閉目錄 ??

int closedir(DIR *dirp); //示例: 簡單的ls程序 int main(int argc, char *argv[]) {if (argc < 2){cerr << "Usage : " << argv[0] << " <directory>" << endl;exit(EXIT_FAILURE);}DIR *dir = opendir(argv[1]);if (dir == NULL)err_exit("opendir error");struct dirent *ent;while ((ent = readdir(dir)) != NULL){//過濾掉隱藏文件if (ent->d_name[0] == '.')continue;cout << ent->d_name << "\ti-node: " << ent->d_ino<< ", length: " << ent->d_reclen << endl;}closedir(dir); }

9.mkdir

int mkdir(const char *pathname, mode_t mode);

10.rmdir:?刪除空目錄

int rmdir(const char *pathname);

11.?Chmod,?fchmod更改權限

int chmod(const char *path, mode_t mode); int fchmod(int fd, mode_t mode);

12.chown,fchown更改文件所有者/所屬組

int chown(const char *path, uid_t owner, gid_t group); int fchown(int fd, uid_t owner, gid_t group);

總結

以上是生活随笔為你收集整理的文件I/O实践(1) --基础API的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。