Linux文件

LINUX下文件的操作

以下均已為ubuntu 18.04 LTS環(huán)境。

  1. 文件的打開(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)行只讀、只寫、讀寫操作

  2. 文件的讀取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ù)。

  3. 文件的寫入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ù)。
  1. 文件的關(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;
}
  1. 文件指針的移動(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)頭偏移。
  2. 文件描述符的復(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)互不影響。
  3. 文件狀態(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文件屬性的操作

  1. 獲取文件屬性通過(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)判斷不同的文件類型。

  2. 設(shè)置文件屬性

    1. 文件權(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);
        }
        
    2. 文件所有者和所有組的修改: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í),需要牢記修改的UIDGID防止改錯(cuò)。

    3. 文件大小的修改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ù)有序性打亂。

    4. 文件時(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í)間。
    5. 文件保留權(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 等等。

    6. 文件的移動(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下如果該文件已存在,則刪除舊文件。

    7. 文件的刪除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è)所有的文件。

    8. 目錄的操作mkdir/rmdir/getcwd/chdir/fchdir/opendir/readdir/closedir

      1. 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自己加。

      2. rmdir

        • 函數(shù)的原型:

          *int rmdir(const char pathname);

        • 需要的頭文件:

          #include <unistd.h>

        刪除指定路徑下的文件。

      3. getcwd

        • 函數(shù)的原型:

          **char getcwd(char buf, size_t size);

        • 需要的頭文件:

          #include <unistd.h>

        將當(dāng)前工作目錄的絕對(duì)路徑復(fù)制到參數(shù)buf所指的內(nèi)存空間。

      4. chdir

        • 函數(shù)的原型:

          *int chdir(const char path);
          int fchdir(int fd);

        • 需要的頭文件:

          #include <unistd.h>

        改變當(dāng)前的工作路徑到指定的路徑。

      5. opendir

        • 函數(shù)的原型:

          **DIR opendir(const char name);
          *DIR fdopendir(int fd);

        • 需要的頭文件:

          #include <sys/types.h>
          #include <dirent.h>

        根據(jù)路徑或者文件描述符打開(kāi)一個(gè)目錄。 目錄返回一個(gè)DIR類型的文件目錄流。

      6. 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)閉文件目錄。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,345評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,494評(píng)論 3 416
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 176,283評(píng)論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,953評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,714評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,186評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,410評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,940評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,776評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,976評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,210評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,642評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,878評(píng)論 1 286
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,654評(píng)論 3 391
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,958評(píng)論 2 373