LINUX下文件的操作
以下均已為ubuntu 18.04 LTS環(huán)境。
-
文件的打開(kāi)
open
-
打開(kāi)文件的函數(shù)原型:
*open(const char pathname, int flags);
*open(const char pathname, int flags, mode_t mode);
-
打開(kāi)文件函數(shù)需要的頭文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
文件的打開(kāi)需要文件的絕對(duì)或相對(duì)路徑字符串,還有文件打開(kāi)的方式。
一般常用有以下三種。
對(duì)應(yīng)的標(biāo)志 含義 O_RDONLHY 只讀 O_WRONLY 只寫 O_RDWR 讀寫 O_CREAT 文件不存在就創(chuàng)建這個(gè)文件(需要使用mode_t mode 參數(shù)進(jìn)行文件權(quán)限的設(shè)置) O_TRUNC 文件存在并且以可寫的形式打開(kāi)時(shí),此標(biāo)志將會(huì)把文件長(zhǎng)度清零,即原文件格式化 O_APPEND 寫入的數(shù)據(jù)添加到文件的尾部 并且前三種的標(biāo)志互相沖突,不可以同時(shí)進(jìn)行只讀、只寫、讀寫操作
-
-
文件的讀取
read
-
文件讀取的函數(shù)原型:
*read(int fd, void buf, size_t count);
-
需要用到的頭文件:
#include <unistd.h>
文件的讀取需要注意的是每個(gè)參數(shù)的意義:
? fd 對(duì)應(yīng)的是 打開(kāi)文件時(shí)的文件描述符,文件描述符對(duì)應(yīng)的是一個(gè)int值。當(dāng)打開(kāi)文件失敗時(shí),open函數(shù)對(duì)應(yīng)返回 -1 作為讀取失敗的標(biāo)志。
? buf 是文件讀取寫入的字符串。
? count 為一次讀取的字節(jié)個(gè)數(shù)。
-
-
文件的寫入
write
-
文件寫入的函數(shù)原型:
*write(int fd, const void buf, size_t count);
-
需要用到的頭文件:
#include <unistd.h>
fd 對(duì)應(yīng)的是 打開(kāi)文件時(shí)的文件描述符,文件描述符對(duì)應(yīng)的是一個(gè)int值。當(dāng)打開(kāi)文件失敗時(shí)open函數(shù)對(duì)應(yīng)返回 -1 作為讀取失敗的標(biāo)志。
-
buf 是寫入文件的字符串。
count 為一次寫入的字節(jié)個(gè)數(shù)。
-
文件的關(guān)閉
close
-
關(guān)閉文件的原型:
close(int fd);
-
需要的頭文件:
#include <unistd.h>
關(guān)閉文件的讀取,只需要文件的描述符即可。關(guān)閉文件應(yīng)在所有文件操作之后。
-
//利用以上文件的操作,可以完成對(duì)一個(gè)的復(fù)制功能。
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv){
//成功讀取的數(shù)據(jù)個(gè)數(shù),設(shè)置為1 ,確保進(jìn)入循環(huán)
int success = 1;
//文件描述符定義
int fd1;
int fd2;
//復(fù)制中轉(zhuǎn)字符數(shù)組
char copy[100];
//argv[1]為要復(fù)制的文件名,argv[2]為復(fù)制的副本文件名
//先判斷參數(shù)是否夠
if(argc < 3){
printf("參數(shù)不夠!\n");
}
//再打開(kāi)文件
//打開(kāi)文件失敗
if((fd1 = open(argv[1], O_RDONLY)) == -1){
perror("open file1 failed\n");
exit(0);
}
if((fd2 = open(argv[2], O_WRONLY)) == -1){//在這個(gè)判斷條件里文件描述符不能用括號(hào)括!!!!!
perror("open file2 failed\n");
}
// fd2 = open(argv[2], O_WRONLY);
while(success){
//成功讀取的字符個(gè)數(shù)
//int sussess;
success = read(fd1, copy, 100);
write(fd2, copy, success);
}
//關(guān)閉兩個(gè)文件
close(fd1);
close(fd2);
return 0;
}
-
文件指針的移動(dòng)
lseek
-
指針移動(dòng)函數(shù)的原型:
lseek(int fd, off_t offset, int whence);
-
需要的頭文件
#include <sys/types.h>
#include <unistd.h>
移動(dòng)的三種狀態(tài) 操作及意義 SEEK_SET 將文件指針移動(dòng)到文件的開(kāi)始處,offset是指針相對(duì)SEEK_SET的偏移位置,所以此時(shí)offset只有正值,即只能向文件的末尾偏移。 SEEK_CUR 對(duì)于當(dāng)前文件指針指向進(jìn)行偏移,可正可負(fù) SEEK_END 文件指針指向文件的尾部,只能讀取負(fù)值,即向文件的開(kāi)頭偏移。
-
-
文件描述符的復(fù)制
dup,dup2
-
函數(shù)的原型:
int dup(int oldfd);
int dup2(int oldfd, int newfd);
-
所需的頭文件:
#include <unistd.h>
函數(shù) 意義 dup()
返回一個(gè)和原先文件指針指向相同的地方,不管是新的指針移動(dòng),還是舊的指針移動(dòng),都會(huì)影響另外一個(gè)指針的移動(dòng),且未移動(dòng)的指針與移動(dòng)了的指針移動(dòng)狀態(tài)相同 dup2
自定義一個(gè)新的文件指針,且指針狀態(tài)互不影響。
-
-
文件狀態(tài)函數(shù)
fcntl
-
函數(shù)原型:
int fcntl(int fd, int cmd );
int fcntl(int fd, int cmd, long arg);
*int fcntl(int fd, int cmd, struct flock lock);
-
需要的頭文件:
#include <unistd.h>
#include <fcntl.h>
cmd值 意義 F_DUPFD 可以復(fù)制文件的描述符 F_GETFD 獲取文件描述符的close-on-exec標(biāo)志 F_SETFD 用來(lái)設(shè)置文件描述符close-on-exec標(biāo)志的第三個(gè)參數(shù)arg的最后一位。 F_GETFL 用來(lái)獲得文件的打開(kāi)方式 F_njSETFL 設(shè)置文件打開(kāi)的第三個(gè)參數(shù)arg指定的方式
-
由fcntl
文件產(chǎn)生的文件記錄鎖。
*int fcntl(int fd, int cmd, struct flock lock);
//struct flock *lock結(jié)構(gòu)體原型
struct flock {
short l_type;/*設(shè)置文件鎖的狀態(tài) F_RDLCK|F_WRLCK|F_UNLCK*/
short l_whence;/*跟文件的移動(dòng)SEEK_SET or SEEK_CUR or SEEK_END一樣*/
off_t l_start;/*開(kāi)始設(shè)置鎖的位移*/
off_t l_len;/*設(shè)置鎖的長(zhǎng)度為多大*/
pid_t l_pid;/*鎖的主進(jìn)程PID*/
}
//根據(jù)鎖的狀態(tài)來(lái)設(shè)置文件鎖,首先獲得狀態(tài),是否可以加鎖。可以,加鎖。不可以,等待鎖解開(kāi)。
//同一個(gè)進(jìn)程可以對(duì)鎖的狀態(tài)進(jìn)行隨意更改,但是不同進(jìn)程之間,不可以隨意更改。需要更改,首先要獲得狀態(tài)。
//首先對(duì)lock結(jié)構(gòu)體進(jìn)行填充,確定想要給鎖加的狀態(tài)。之后進(jìn)行判斷能否加鎖。
lock.l_type = F_RDLCK;//設(shè)置讀鎖
lock.l_whence = SEEK_SET;//鎖的偏移量起始位置
lock.l_start = 0;//
lock.l_len = 0;//鎖的區(qū)域從0開(kāi)始,到最大可能到的地方。
fcntl(fd, F_GETLK, lock);//進(jìn)程試圖獲取文件是否可以加鎖。
fcntl(fd, F_SETLK, lock);//設(shè)置文件鎖
linux文件屬性的操作
-
獲取文件屬性
通過(guò)stat結(jié)構(gòu)體來(lái)獲取
struct stat { dev_t st_dev; /* ID of device containing file */ ino_t st_ino; /* Inode number */ mode_t st_mode; /* 文件的類型和權(quán)限 */ nlink_t st_nlink; /* 硬鏈接的數(shù)目 */ uid_t st_uid; /* 用戶所有者ID */ gid_t st_gid; /* 用戶所在組ID */ dev_t st_rdev; /* Device ID (if special file) */ off_t st_size; /* 文件大小 */ blksize_t st_blksize; /* 文件所占?jí)K大小 */ blkcnt_t st_blocks; /*Since Linux 2.6, the kernel supports nanosecond precision for the following timestamp fields. For the details before Linux 2.6, see NOTES. */ struct timespec st_atim; /* 最后訪問(wèn)時(shí)間 */ struct timespec st_mtim; /* 最后修改時(shí)間 */ struct timespec st_ctim; /* 上次狀態(tài)修改時(shí)間 */ #define st_atime st_atim.tv_sec /* Backward compatibility */ #define st_mtime st_mtim.tv_sec #define st_ctime st_ctim.tv_sec };
利用這個(gè)可以完美的將文件的信息打印出來(lái)。
//這是一個(gè)系統(tǒng)內(nèi)部 舉出來(lái)的例子 #include <sys/types.h> #include <sys/stat.h> #include <time.h> #include <stdio.h> #include <stdlib.h> #include <sys/sysmacros.h> int main(int argc, char *argv[]) { struct stat sb; if (argc != 2) { fprintf(stderr, "Usage: %s <pathname>\n", argv[0]); exit(EXIT_FAILURE); } if (lstat(argv[1], &sb) == -1) { perror("lstat"); exit(EXIT_FAILURE); } printf("ID of containing device: [%lx,%lx]\n", (long) major(sb.st_dev), (long) minor(sb.st_dev)); printf("File type: "); switch (sb.st_mode & S_IFMT) { case S_IFBLK: printf("block device\n"); break; case S_IFCHR: printf("character device\n"); break; case S_IFDIR: printf("directory\n"); break; case S_IFLNK: printf("symlink\n"); break; case S_IFREG: printf("regular file\n"); break; case S_IFSOCK: printf("socket\n"); break; default: printf("unknown?\n"); break; } printf("I-node number: %ld\n", (long) sb.st_ino); printf("Mode: %lo (octal)\n", (unsigned long) sb.st_mode); printf("Link count: %ld\n", (long) sb.st_nlink); printf("Ownership: UID=%ld GID=%ld\n", (long) sb.st_uid, (long) sb.st_gid); printf("Preferred I/O block size: %ld bytes\n", (long) sb.st_blksize); printf("File size: %lld bytes\n", (long long) sb.st_size); printf("Blocks allocated: %lld\n", (long long) sb.st_blocks); printf("Last status change: %s", ctime(&sb.st_ctime)); printf("Last file access: %s", ctime(&sb.st_atime)); printf("Last file modification: %s", ctime(&sb.st_mtime)); exit(EXIT_SUCCESS); } //詳細(xì)的寫了一個(gè)文件的具體信息。
st_mode利用了特征位來(lái)表示文件類型
S_IFMT
為位遮罩
可以利用st_mode & S_IFMT
最終判斷文件的類型。也可以使用
宏 意義 S_ISLNK(st_mode) 判斷文件是否為符號(hào)鏈接文件。 此外還有很多宏,對(duì)應(yīng)判斷不同的文件類型。
-
設(shè)置文件屬性
-
文件權(quán)限的修改
chmod/fchmod
-
函數(shù)的原型:
*int chmod (const char pathname, mod_t mode)
int fchmod(int fd, mod_t mode)
-
需要的頭文件:
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h> #include <stdlib.h> #include <sys/stat.h> int main(int argc, char **argv){ if(argc != 2){ exit(0); } chmod(argv[1], S_IRUSER|S_IWUSR|S_IXUSR|S_IRGRP);//-rwxr----- int fd = open(argv[1], O_RDWR); fchmod(fd, S_IRUSER|S_IWUSR|S_IXUSR|S_IRGRP);//-rwxr----- close(fd); }
-
-
文件所有者和所有組的修改:
chown/fchown/lchown
-
函數(shù)的原型:
*int chown(const char pathname, uid_t owner, gid_t group);
int fchown( int fd, uid_t owner, gid_t group);
*int lchown(const char pathname, uid_t owner, gid_t group);
-
需要的頭文件:
#include <fcntl.h>
#include <unistd.h>
修改時(shí),需要牢記修改的
UID
和GID
防止改錯(cuò)。
-
-
文件大小的修改
truccate/ftruccate
-
函數(shù)的原型:
*int truncate(const char path, off_t length);
int ftruncate(int fd, off_t length); -
需要的頭文件:
#include <unistd.h>
#include <sys/types.h>
最好不要用,將文件修改小時(shí),會(huì)丟失尾部數(shù)據(jù),當(dāng)文件修改大時(shí),會(huì)將尾部數(shù)據(jù)有序性打亂。
-
-
文件時(shí)間的修改
utime
-
函數(shù)原型:
**int utime(const char filename, const struct utimbuf times)
*int utimes(const char filename, const struct timeval times[2]);
-
需要的頭文件:
#include <sys/types.h>
#include <utime.h>#include <sys/time.h>
可以修改文件的
st_ctim``st_mtim
。- - utime 將第一個(gè)參數(shù)文件的存取時(shí)間改為第二個(gè)參數(shù)buf的actim域,把修改時(shí)間改為第二個(gè)參數(shù)buf的modtim域,如果buf為一個(gè)空指針,則都改為當(dāng)前時(shí)間。 -
-
文件保留權(quán)限
umask
-
函數(shù)原型:
mode_t umask(mode_t mask);
-
需要的頭文件:
#include <sys/types.h>
#include <sys/stat.h>
創(chuàng)建文件或目錄的權(quán)限,
umak & st_mode
。參數(shù)mask為文件所有的權(quán)限。st_mode 為 S_IRUSR 等等。
-
-
文件的移動(dòng)
rename
- 函數(shù)的原型:
**int rename(const char oldpath, const char newpath);
**int renameat(int olddirfd, const char oldpath, int newdirfd, const char newpath);
**int renameat2(int olddirfd, const char oldpath, int newdirfd, const char newpath, unsigned int flags);
-
需要的頭文件:
#include <stdio.h>
#include <fcntl.h>
#include <stdio.h>
文件會(huì)將 oldpath 所描述的文件名稱改為參數(shù)newpath。newpath下如果該文件已存在,則刪除舊文件。
-
文件的刪除
unlink/remove
-
函數(shù)的原型:
int unlink(const char *pathname);
//不懂 int unlinkat(int dirfd, const char *pathname, int flags);
-
需要的頭文件:
include <unistd.h>
-
函數(shù)的原型:
int remove(const char *pathname);
-
需要的頭文件:
include <stdio.h>
使用ulink時(shí),在進(jìn)程打開(kāi)文件的時(shí)候,即使文件被銷毀。但是接下來(lái)的對(duì)銷毀文件的操作也成立。因?yàn)樵谶M(jìn)程的結(jié)束,即使因?yàn)殇N毀后還有對(duì)文件的操作,也不會(huì)緩存這個(gè)所有的文件。
-
-
目錄的操作
mkdir/rmdir/getcwd/chdir/fchdir/opendir/readdir/closedir
-
mkdir
-
函數(shù)的原型:
*int mkdir(const char pathname, mode_t mode);
-
需要的頭文件:
#include <sys/stat.h>
#include <sys/types.h>
創(chuàng)建一個(gè)文件夾,創(chuàng)建在pathname路徑下。權(quán)限mode自己加。
-
-
rmdir
-
函數(shù)的原型:
*int rmdir(const char pathname);
-
需要的頭文件:
#include <unistd.h>
刪除指定路徑下的文件。
-
-
getcwd
-
函數(shù)的原型:
**char getcwd(char buf, size_t size);
-
需要的頭文件:
#include <unistd.h>
將當(dāng)前工作目錄的絕對(duì)路徑復(fù)制到參數(shù)buf所指的內(nèi)存空間。
-
-
chdir
-
函數(shù)的原型:
*int chdir(const char path);
int fchdir(int fd); -
需要的頭文件:
#include <unistd.h>
改變當(dāng)前的工作路徑到指定的路徑。
-
-
opendir
-
函數(shù)的原型:
**DIR opendir(const char name);
*DIR fdopendir(int fd); -
需要的頭文件:
#include <sys/types.h>
#include <dirent.h>
根據(jù)路徑或者文件描述符打開(kāi)一個(gè)目錄。 目錄返回一個(gè)DIR類型的文件目錄流。
-
-
readdir
-
函數(shù)的原型:
**struct dirent readdir(DIR dirp);
-
需要的頭文件:
#include <dirent.h>
open目錄返回的DIR目錄指針參數(shù),返回一個(gè)struct dirent類型的指針。里邊存放文件的d_ino,d_reclen (d_name的長(zhǎng)度),d_off不懂。
-
-
-
7. `closedir`
- 函數(shù)的原型:
**int closedir(DIR *dirp);**
- 需要的頭文件
**#include <sys/types.h>**
**#include <dirent.h>**
根據(jù)文件目錄流,關(guān)閉文件目錄。