此為牛客網Linux C++課程1.20課程筆記。
1.open函數
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:八進制的數,表示創建出的新的文件的操作權限,比如:0775
flags有三個必選項:O_RDONLY, O_WRONLY, O_RDWR 。
分別是只讀、只寫和讀寫,這三個設置是互斥的。
flags還有一些非必選項:
O_CREAT 如果文件不存在則創建該文件
O_EXCL 如果使用O_CREAT選項且文件存在,則返回錯誤消息
O_NOCTTY 如果文件為終端,那么終端不可以調用open系統調用的那個進程的控制終端
O_TRUNC 如果文件已經存在則刪除文件中原有數據
O_APPEND 以追加的方式打開
必選項和非必選項可以組合使用,中間用 | 隔開,如O_RDWR | O_CREAT | O_TRUNC。
mode參數用一個八進制數與取反后的當前進程的umask掩碼進行按位與,得到新文件的操作權限。
返回值:返回一個新的文件描述符,如果調用失敗,返回-1。
2. 關于errno
errno是Linux系統函數里面的一個全局變量,記錄的是最近一次錯誤的錯誤號。
在/usr/include/asm-generic/errno.h和/usr/include/asm-generic/errno-base.h中記錄了定義了這些錯誤號,如圖:
一個錯誤號對應一個錯誤信息。
我們可以用perror函數來打印errno對應的錯誤信息
#include <stdio.h>
void perror(const char *s);//作用:打印errno對應的錯誤描述
s參數:用戶描述,比如hello,最終輸出的內容是 hello:xxx(實際的錯誤描述)。
如以下示例程序,打開一個不存在的文件a.txt
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>int main() {// 打開一個文件int fd = open("a.txt", O_RDONLY);if(fd == -1) {perror("open file");}// 關閉close(fd);return 0;
}
輸出的結果是:
是s參數+實際錯誤描述的組合。
3. read和write函數
read函數:
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
參數:
- fd:文件描述符,open得到的,通過這個文件描述符操作某個文件
- buf:需要讀取數據存放的地方,數組的地址(傳出參數)
- count:指定的數組的大小
返回值:一個整數,有以下情況:
- 成功:
>0: 返回實際的讀取到的字節數
=0:文件已經讀取完了 - 失敗:-1 ,并且設置errno。
write函數:
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
參數:
- fd:文件描述符,open得到的,通過這個文件描述符操作某個文件
- buf:要往磁盤寫入的數據,數據
- count:要寫的數據的實際的大小
返回值:
- 成功:實際寫入的字節數
- 失敗:返回-1,并設置errno
示例程序如下,該程序能夠讀入一個文件中的全部內容,復制到一個新創建的文件中:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>int main()
{int fdread = open("english.txt", O_RDONLY);if(fdread == -1) {perror("open english.txt");return -1;}int fdwrite = open("copy.txt", O_WRONLY | O_CREAT, 0664);if(fdwrite == -1) {perror("create and open aftercopy.txt");return -1;}char buffer[1024] = {0};int len = 0;while((len = read(fdread, buffer, sizeof(buffer))) > 0) {write(fdwrite, buffer, len);}close(fdwrite);close(fdread);return 0;
}
4. lseek函數
#include <sys/types.h>
include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
參數:
- fd:文件描述符,通過open得到的,通過這個fd操作某個文件
- offset:偏移量
- whence:以下三選一
SEEK_SET
設置文件指針的偏移量
SEEK_CUR
設置偏移量:當前位置 + 第二個參數offset的值
SEEK_END
設置偏移量:文件大小 + 第二個參數offset的值
返回值:返回文件指針的位置
該函數主要有以下作用:
- 移動文件指針到文件頭:lseek(fd, 0, SEEK_SET);
- 獲取當前文件指針的位置:lseek(fd, 0, SEEK_CUR);
- 獲取文件長度:lseek(fd, 0, SEEK_END);
- 拓展文件的長度,當前文件10b, 110b, 增加了100個字節:lseek(fd, 100, SEEK_END), 注意:需要寫一次數據。
擴展文件長度的示例程序如下:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>int main() {int fd = open("hello.txt", O_RDWR);if(fd == -1) {perror("open");return -1;}// 擴展文件的長度int ret = lseek(fd, 100, SEEK_END);if(ret == -1) {perror("lseek");return -1;}// 寫入一個空數據write(fd, " ", 1);// 關閉文件close(fd);return 0;
}