Linux 環境編程之文件I/O:文件創建、打開、關閉

文件打開

用open或openat可打開或創建文件

#include <fcntl.h>
int open( const char *path, int flags,.../*mode_t mode*/);
int openat( int fd, const char *path, int flags,.../*mode_t mode*/);

參數:

  • path:文件路徑(帶文件名)
  • flag:打開選項
    • 以下選項必須指定且只能指定一個
      • O_RDONLY:只讀,一般爲0
      • O_WRONLY:只寫,一般爲1
      • O_RDWR:可讀寫,一般爲2
      • O_EXEC:只執行打開
      • O_SEARCH:只搜索打開(用於目錄)
    • 以下常量可選
      • O_APPEND:追加到文件末尾
      • O_CREAT:文件不存在則創建,mode參數指定新文件訪問權限位
      • O_DIRECTORY:若path引用的不是目錄,則出錯。
      • O_EXCL:與O_CREAT合用,文件不存在則創建,存在則報錯,使得檢測與創建合併爲原子操作。
      • O_NONBLOCK:若path引用的是fifo、塊特殊文件或字符特殊文件,則標誌着此次打開和後續IO操作都不阻塞。
      • O_SYNC:使每次write等待物理IO完成。
      • O_TRUNC:若文件存在且以只寫/讀寫方式打開,則將文件截斷爲0.
      • O_DSYNC:使每次write等待物理IO完成,若寫不影響讀,則不等待文件屬性更新。
      • ……

返回值:最小未用過的文件描述符的值;出錯返回 -1

open 與openat 區別

兩者區別在於fd的值,有3種情況:

  • 若path是絕對路徑,則忽略fd,openat 等於open
  • 若path是相對路徑,則fd指定了path的參照地址,fd引用的是打開的目錄
  • path爲相對路徑,fd取特殊值AT_FDCWD,則path參照當前目錄,openat與open等同。

文件創建

create函數用於創建文件

#include<fcntl.h>
int creat(const char *path, mode_t mode);

等價於:

open(path, O_WRONLY|O_CREAT|O_TRUNC, mode)

返回值:文件描述符,出錯返回-1。

文件關閉

close 用於關閉文件

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

關閉文件會釋放該進程加在文件上的所有記錄鎖;

進程終止時,內核自動關閉它所打開的文件。

 

測試代碼:

#include <fcntl.h>
#include <stdio.h>
#include <string.h>
int main()
{
	printf("rdonly:%d wronly:%d rdwr:%d\n", O_RDONLY, O_WRONLY, O_RDWR); // 0 1 2

	// 文件不存在
	int fd = open("./filenoexist.txt", O_RDONLY);
	if (fd < 0)
		printf("open fail\n");
	else
		close(fd);

	// 創建文件
	//fd = open("./filenoexist.txt", O_CREAT, 0400); // 創建權限爲只讀,後面的寫嘗試都會失敗
	fd = open("./filenoexist.txt", O_CREAT, 0600);
	if (fd < 0)
		printf("create fail\n");
	else
		printf("create success\n");
	close(fd);

	//再次創建,但是必須不存在
	fd = open("./filenoexist.txt", O_CREAT | O_EXCL);
	if (fd < 0)
		printf("file already exists\n");
	else
		close(fd);

	// 只讀打開,嘗試寫
	fd = open("./filenoexist.txt", O_RDONLY);
	char buf[64];
	snprintf(buf, sizeof(buf), "hello world.");
	//int ret = write(fd, buf, sizeof(buf)); // 可以看看用sizeof和strlen的區別
	int ret = write(fd, buf, strlen(buf));
	if (ret < 0)
		printf("read only write fail.\n");
	else
		printf("read only write succ:%s.\n", buf);
	close(fd);

	// 只寫打開,嘗試讀
	fd = open("./filenoexist.txt", O_WRONLY);
	memset(buf, 0x0, sizeof(buf));
	ret = read(fd, buf, sizeof(buf));
	if (ret < 0)
		printf("write only read fail.\n");
	else
		printf("write only read succ:%s.\n", buf);
	close(fd);

	// 讀寫打開,嘗試寫
	fd = open("./filenoexist.txt", O_RDWR);
	memset(buf, 0x0, sizeof(buf));
	snprintf(buf, sizeof(buf), "hello world.");
	ret = write(fd, buf, strlen(buf));
	if (ret < 0)
		printf("write fail.\n");
	close(fd);

	// 讀寫打開,嘗試讀
	fd = open("./filenoexist.txt", O_RDWR);
	char rdbuf[128];
	memset(rdbuf, 0x0, sizeof(rdbuf));
	ret = read(fd, rdbuf, sizeof(rdbuf));
	if (ret < 0)
		printf("read fail.\n");
	else
		printf("read succ:%s.\n", rdbuf);
	close(fd);


	// 追加文件
	fd = open("./filenoexist.txt", O_WRONLY|O_APPEND);
	memset(buf, 0x0, sizeof(buf));
	snprintf(buf, sizeof(buf), "hello world.");
	ret = write(fd, buf, strlen(buf));
	if (ret < 0)
		printf("append write fail.\n");
	else
		printf("append succ:%s.\n", buf);
	close(fd);

	// 讀寫打開,嘗試讀
	fd = open("./filenoexist.txt", O_RDWR);
	//char rdbuf[128];
	memset(rdbuf, 0x0, sizeof(rdbuf));
	ret = read(fd, rdbuf, sizeof(rdbuf));
	if (ret < 0)
		printf("read fail.\n");
	else
		printf("read succ:%s.\n", rdbuf);
	close(fd);

	// 截斷打開
	fd = open("./filenoexist.txt", O_WRONLY|O_TRUNC);
	memset(buf, 0x0, sizeof(buf));
	snprintf(buf, sizeof(buf), "talk is cheap.");
	ret = write(fd, buf, strlen(buf));
	if (ret < 0)
		printf("write fail.\n");
	close(fd);
}

編譯運行,結果:

rdonly:0 wronly:1 rdwr:2
create success
file already exists
read only write fail.
write only read fail.
read succ:hello world.p..
append succ:hello world..
read succ:hello world.p.hello world..

最後一行hello world 之間的p,是因爲代碼中“talk is cheap” 末尾的p,“hello world”沒有覆蓋完,留下的~

編程學習要通過實踐才能進步,即使照着書上代碼抄,也得嘗試修改,看看輸出結果和預想的是否相同,不同是什麼原因。

 

參考:

Linux C API 參考手冊

LinuxAPI

《Unix環境高級編程》3.3-3.5 小節

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章