Linux文件

2018-07-27  本文已影响0人  快扶我起来搬砖

LINUX下文件的操作

以下均已为ubuntu 18.04 LTS环境。

  1. 文件的打开open

    • 打开文件的函数原型:

      *open(const char pathname, int flags);

      *open(const char pathname, int flags, mode_t mode);

    • 打开文件函数需要的头文件:

      #include <sys/types.h>

      #include <sys/stat.h>
      #include <fcntl.h>

    文件的打开需要文件的绝对或相对路径字符串,还有文件打开的方式。

    一般常用有以下三种。

    对应的标志 含义
    O_RDONLHY 只读
    O_WRONLY 只写
    O_RDWR 读写
    O_CREAT 文件不存在就创建这个文件(需要使用mode_t mode 参数进行文件权限的设置)
    O_TRUNC 文件存在并且以可写的形式打开时,此标志将会把文件长度清零,即原文件格式化
    O_APPEND 写入的数据添加到文件的尾部

    并且前三种的标志互相冲突,不可以同时进行只读、只写、读写操作

  2. 文件的读取read

    • 文件读取的函数原型:

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

    • 需要用到的头文件:

      #include <unistd.h>

    文件的读取需要注意的是每个参数的意义:

    ​ fd 对应的是 打开文件时的文件描述符,文件描述符对应的是一个int值。当打开文件失败时,open函数对应返回 -1 作为读取失败的标志。

    ​ buf 是文件读取写入的字符串。

    ​ count 为一次读取的字节个数。

  3. 文件的写入write

    • 文件写入的函数原型:

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

    • 需要用到的头文件:

      #include <unistd.h>

      fd 对应的是 打开文件时的文件描述符,文件描述符对应的是一个int值。当打开文件失败时open函数对应返回 -1 作为读取失败的标志。

    buf 是写入文件的字符串。
    
    count 为一次写入的字节个数。
  1. 文件的关闭close

    • 关闭文件的原型:

      close(int fd);

    • 需要的头文件:

      #include <unistd.h>

      关闭文件的读取,只需要文件的描述符即可。关闭文件应在所有文件操作之后。

//利用以上文件的操作,可以完成对一个的复制功能。
#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){
    

    //成功读取的数据个数,设置为1 ,确保进入循环
    int success = 1;
    //文件描述符定义
    int fd1;
    int fd2;

    //复制中转字符数组
    char copy[100];

    //argv[1]为要复制的文件名,argv[2]为复制的副本文件名
    //先判断参数是否够
    
    if(argc < 3){
        printf("参数不够!\n");
    }
    //再打开文件
    //打开文件失败
    if((fd1 = open(argv[1], O_RDONLY)) == -1){
    
        perror("open file1 failed\n");
        exit(0);
    }
    if((fd2 = open(argv[2], O_WRONLY)) == -1){//在这个判断条件里文件描述符不能用括号括!!!!!
        
        perror("open file2 failed\n");
    }

//  fd2 = open(argv[2], O_WRONLY);

    while(success){
        //成功读取的字符个数
        //int sussess;
        success = read(fd1, copy, 100);
        write(fd2, copy, success);  
    }
    //关闭两个文件
    close(fd1);
    close(fd2);
    return 0;
}
  1. 文件指针的移动lseek

    • 指针移动函数的原型:

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

    • 需要的头文件

      #include <sys/types.h>

      #include <unistd.h>

      移动的三种状态 操作及意义
      SEEK_SET 将文件指针移动到文件的开始处,offset是指针相对SEEK_SET的偏移位置,所以此时offset只有正值,即只能向文件的末尾偏移。
      SEEK_CUR 对于当前文件指针指向进行偏移,可正可负
      SEEK_END 文件指针指向文件的尾部,只能读取负值,即向文件的开头偏移。
  2. 文件描述符的复制dup,dup2

    • 函数的原型:

      int dup(int oldfd);

      int dup2(int oldfd, int newfd);

    • 所需的头文件:

      #include <unistd.h>

      函数 意义
      dup() 返回一个和原先文件指针指向相同的地方,不管是新的指针移动,还是旧的指针移动,都会影响另外一个指针的移动,且未移动的指针与移动了的指针移动状态相同
      dup2 自定义一个新的文件指针,且指针状态互不影响。
  3. 文件状态函数fcntl

    • 函数原型:

      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_GETFD 获取文件描述符的close-on-exec标志
      F_SETFD 用来设置文件描述符close-on-exec标志的第三个参数arg的最后一位。
      F_GETFL 用来获得文件的打开方式
      F_njSETFL 设置文件打开的第三个参数arg指定的方式

fcntl文件产生的文件记录锁。

*int fcntl(int fd, int cmd, struct flock lock);

//struct flock *lock结构体原型
struct flock {
 short l_type;/*设置文件锁的状态 F_RDLCK|F_WRLCK|F_UNLCK*/
    short l_whence;/*跟文件的移动SEEK_SET or SEEK_CUR or SEEK_END一样*/
    off_t l_start;/*开始设置锁的位移*/
    off_t l_len;/*设置锁的长度为多大*/
    pid_t l_pid;/*锁的主进程PID*/
}
//根据锁的状态来设置文件锁,首先获得状态,是否可以加锁。可以,加锁。不可以,等待锁解开。
//同一个进程可以对锁的状态进行随意更改,但是不同进程之间,不可以随意更改。需要更改,首先要获得状态。
//首先对lock结构体进行填充,确定想要给锁加的状态。之后进行判断能否加锁。
lock.l_type = F_RDLCK;//设置读锁
lock.l_whence = SEEK_SET;//锁的偏移量起始位置
lock.l_start = 0;//
lock.l_len = 0;//锁的区域从0开始,到最大可能到的地方。
fcntl(fd, F_GETLK, lock);//进程试图获取文件是否可以加锁。
fcntl(fd, F_SETLK, lock);//设置文件锁

linux文件属性的操作

  1. 获取文件属性通过stat结构体来获取

    struct stat {
                   dev_t     st_dev;         /* ID of device containing
     file */
                   ino_t     st_ino;         /* Inode number */
                   mode_t    st_mode;        /* 文件的类型和权限 */
                   nlink_t   st_nlink;       /* 硬链接的数目 */
                   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;     /* 文件所占块大小 */
                   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;  /* 最后访问时间 */
                   struct timespec st_mtim;  /* 最后修改时间 */
                   struct timespec st_ctim;  /* 上次状态修改时间 */
    
               #define st_atime st_atim.tv_sec      /* Backward compatibility */
               #define st_mtime st_mtim.tv_sec
               #define st_ctime st_ctim.tv_sec
               };
    

    利用这个可以完美的将文件的信息打印出来。

    //这是一个系统内部 举出来的例子
    #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);
           }
    //详细的写了一个文件的具体信息。
    

    st_mode利用了特征位来表示文件类型

    S_IFMT位遮罩 可以利用 st_mode & S_IFMT最终判断文件的类型。

    也可以使用

    意义
    S_ISLNK(st_mode) 判断文件是否为符号链接文件。

    此外还有很多宏,对应判断不同的文件类型。

  2. 设置文件属性

    1. 文件权限的修改chmod/fchmod

      • 函数的原型:

        *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

      • 函数的原型:

        *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>

        修改时,需要牢记修改的UIDGID防止改错。

    3. 文件大小的修改truccate/ftruccate

      • 函数的原型:

        *int truncate(const char path, off_t length);
        int ftruncate(int fd, off_t length);

      • 需要的头文件:

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

      最好不要用,将文件修改小时,会丢失尾部数据,当文件修改大时,会将尾部数据有序性打乱。

    4. 文件时间的修改utime

      • 函数原型:

        **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 将第一个参数文件的存取时间改为第二个参数buf的actim域,把修改时间改为第二个参数buf的modtim域,如果buf为一个空指针,则都改为当前时间。
    5. 文件保留权限umask

      • 函数原型:

        mode_t umask(mode_t mask);

      • 需要的头文件:

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

      创建文件或目录的权限,umak & st_mode。参数mask为文件所有的权限。

      st_mode 为 S_IRUSR 等等。

    6. 文件的移动rename

      • 函数的原型:

      **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>

      文件会将 oldpath 所描述的文件名称改为参数newpath。newpath下如果该文件已存在,则删除旧文件。

    7. 文件的删除unlink/remove

      • 函数的原型:

        int unlink(const char *pathname);

        //不懂 int unlinkat(int dirfd, const char *pathname, int flags);

      • 需要的头文件:

        include <unistd.h>

      • 函数的原型:

        int remove(const char *pathname);

      • 需要的头文件:

        include <stdio.h>

      使用ulink时,在进程打开文件的时候,即使文件被销毁。但是接下来的对销毁文件的操作也成立。因为在进程的结束,即使因为销毁后还有对文件的操作,也不会缓存这个所有的文件。

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

      1. mkdir

        • 函数的原型:

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

        • 需要的头文件:

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

        创建一个文件夹,创建在pathname路径下。权限mode自己加。

      2. rmdir

        • 函数的原型:

          *int rmdir(const char pathname);

        • 需要的头文件:

          #include <unistd.h>

        删除指定路径下的文件。

      3. getcwd

        • 函数的原型:

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

        • 需要的头文件:

          #include <unistd.h>

        将当前工作目录的绝对路径复制到参数buf所指的内存空间。

      4. chdir

        • 函数的原型:

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

        • 需要的头文件:

          #include <unistd.h>

        改变当前的工作路径到指定的路径。

      5. opendir

        • 函数的原型:

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

        • 需要的头文件:

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

        根据路径或者文件描述符打开一个目录。 目录返回一个DIR类型的文件目录流。

      6. readdir

        • 函数的原型:

          **struct dirent readdir(DIR dirp);

        • 需要的头文件:

          #include <dirent.h>

        open目录返回的DIR目录指针参数,返回一个struct dirent类型的指针。里边存放文件的d_ino,d_reclen (d_name的长度),d_off不懂。

  7. `closedir`

     - 函数的原型:

       **int closedir(DIR *dirp);**

     - 需要的头文件

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

       **#include <dirent.h>**

     根据文件目录流,关闭文件目录。
上一篇下一篇

猜你喜欢

热点阅读