Linux文件操作[提升函数]

简介: Linux文件操作[提升函数]

@[toc]

前言

上一篇文章介绍了一下关于在Linux中对于文件操作的简单函数,但是只学习了简单函数对文件的一些复杂操作是不太行的,所以这篇文章给大家介绍一下对文件操作的一些复杂函数。

一、stat函数

stat函数是可以获取文件的一些信息的,这些信息存放在一个结构体中,通过调用这个函数获取文件的信息,然后通过返回的结构体将文件的信息读取出来。
函数的原型如下:

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

int stat(const char* path, struct stat* buf);
int fstat(int fd, struct stat *statbuf)
int lstat(const char* pathname, struct stat* buf);
功能:
    获取文件状态信息
    stat和lstat的区别:
        当文件是一个符号链接时,lstat返回的是该符号链接本身的信息;
        而stat返回的是该链接指向的文件的信息。
参数:
    path:文件名
    buf:保存文件信息的结构体
返回值:
    成功:0
    失败:-1

而这个结构体struct stat中的结构如下:

struct stat {
   
    dev_t     st_dev;         /* 包含文件的设备ID */
    ino_t     st_ino;         /* Inode编号 */
    mode_t    st_mode;        /* 文件类型和模式 */
    nlink_t   st_nlink;       /* 硬链接数 */
    uid_t     st_uid;         /* 所有者的用户ID */
    gid_t     st_gid;         /* 组ID */
    dev_t     st_rdev;        /* 设备ID(如果特殊文件) */
    off_t     st_size;        /* 总大小,以字节为单位 */
    blksize_t st_blksize;     /* 文件系统I/O的块大小 */
    blkcnt_t  st_blocks;      /* 已分配512B块的数量 */

    /* 从Linux 2.6开始,内核支持纳秒
        以下时间戳字段的精度。
        Linux 2.6之前版本的详细信息请参见“说明”。 */

    struct timespec st_atim;  /* 最后一次访问时间 */
    struct timespec st_mtim;  /* 最后一次修改时间 */
    struct timespec st_ctim;  /* 最后一次状态更改的时间 */

    #define st_atime st_atim.tv_sec      /* 向后兼容性 */
   #define st_mtime st_mtim.tv_sec
   #define st_ctime st_ctim.tv_sec
};

比如说查看一个文件的信息,代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int main(){
   
        struct stat ps;
        int ret;
        ret = stat("demo1.c", &ps);
        if (ret == -1){
   
                perror("stat");
                return -1;
        }
        printf("%ld", ps.st_dev);
        return 0;
}

上面的代码是查看了一下设备的ID,需要注意的是,在创建结构体的时候不能使用指针的形式,也就是创建struct stat*,这样子是不可以的,如果使用了会出现下面的错误:

stat:bad address

下面就会有一道题,就是使用stat获取文件的用户权限,代码如下:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

int main(){
   
        int ret;
        struct stat ps;
        ret = stat("demo1.c", &ps);
        if (ret == -1){
   
                perror("stat");
                return -1;
        }
        if (ps.st_mode & 0400){
   
                printf("r");
        }
        else{
   
                printf("-");
        }
        if (ps.st_mode & 0200){
   
                printf("w");
        }
        else{
   
                printf("-");
        }
        if (ps.st_mode & 0100){
   
                printf("x");
        }
        else{
   
                printf("-");
        }
        printf("\n");
        return 0;
}

运行后的结果如下:

rw

二、access函数

这个函数是来判断文件是否有某种权限的,函数的原型如下:

#include <unistd.h>
int access(const char* pathname, int mode);
功能:测试指定文件是否具有某种属性
参数:
    pathname:文件名
    mode:文件权限,4种权限
        R_OK:    是否有读写权限
        W_OK:    是否有写权限
        X_OK:    是否有执行权限
        F_OK:    测试文件是否存在
返回值:
    0:有某种权限,或文件存在
    -1:没有,或文件不存在

这个函数相当于来说比较简单,比如说判断一下demo1.c这个文件中是否存在读写权限,那么代码如下:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(){
   
        int ret;
        ret = access("demo1.c", R_OK);
        if (ret == -1){
   
                perror("access");
                return -1;
        }
        else if(ret == 0){
   
                printf("文件有读的权限\n");
        }
        return 0;
}

三、chmod函数

chmod是Linux中的一个指令,是用来修改一个文件的权限的指令,而这里讲的chmod函数也是
来修改文件的权限的,只不过需要我们像调用函数一样调用它。
chmod函数的原型如下:

#include <sys/stat.h>
int chmod(const char* pathname, mode_t mode);
功能:修改文件权限
参数:
    filename:文件名
    mode:权限(8进制数)
返回值:
    成功:0
    失败:-1

例如下面的代码:

#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>

int main(){
   
        int ret;
        ret = chmod("text", 0000);
        if (ret == -1){
   
                perror("chmod");
                return -1;
        }
        return 0;
}

将text文件的权限修改为0000,之前text的权限为:

-rw-rw-r--

执行上面代码后text文件的权限为:

---------

可以发现权限是已经进行了修改。

四、chown函数

这个函数是修改文件所属组和角色的函数,和命令的用法一样,函数的原型如下:

#include <unistd.h>
int chown(const char* pathname, uid_t owner, git_t group);
功能:
    修改文件所有者和所属组
参数:
    pathname:文件或目录名
    owner:文件所有者id,通过查看 /etc/passwd 得到所有者id
    group:文件所属组id,通过 /etc/group 得到用户组id
返回值:
    成功:0
    失败:-1

需要注意一下,这里的ownergroup得填写用户和组的id,需要去到/etc/passwdetc/group文件中去查看,在命令行中输入下面的命令即可查看其中的内容:

cat /etc/passwd
cat /etc/group

可以看到,用户root的id为0,那如果要修改的话就可以在owner这填写0,组也是同样的操作。
如果不想动这个文件的所属组或者所属用户,那可以直接填写-1,这样就可以不修改了。
下面的代码是修改text文件的所属用户:

#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>

int main(){
   
        int ret;
        ret = chown("text", 1004, -1);
        if (ret == -1){
   
                perror("chown");
                return -1;
        }
        return 0;
}

编译后并执行会发现这个程序并没有执行成功,并输出了下面的语句:

chown: Operation not permitted

原因是因为当前用户的权限并不高,如果要执行得需要更高的权限,所以这里需要切换至root用户再来进行执行,这样就能成功的执行了。

五、truncate函数

这个函数是可以修改文件的大小的函数,函数原型如下:

#include <unistd.h>
#include <sys/types.h>
int truncate(const char* path, off_t length);
功能:修改文件大小
参数:
    path:文件名字
    length:指定的文件大小
        a)比用来小,删除后边的部分
        b)比原来大,向后拓展
返回值:
    成功:0
    失败:-1

比如说我创建了一个文件叫做text1
长度为:4,现在我写好了一个程序,程序主要是修改这个文件的大小为100,代码如下:

#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>

int main(){
   
        int ret;
        ret = truncate("text1", 100);
        if (ret == -1){
   
                perror("truncate");
                return -1;
        }
        return 0;
}

执行完这个程序后,查看这个文件的大小,会发现它变成了:100
文件中的内容也增加了一些:
会发现这后面增加的内容看不明白,那这些是什么呢?其实这些就是空洞,后面对文件操作或者是内存操作文件会经常见到,这出现的原因主要是因为你本来写的东西只有4个(3个字符1个\0),而现在要求扩大这个文件,所以就需要一些占位的内容,所以这些占位的内容就是使用空洞来进行占位。
我再修改一下这个文件,将它的大小变为100
然后我将这个文件的大小修改为10,看看这个文件会发生什么。

#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>

int main(){
   
        int ret;
        ret = truncate("text1", 10);
        if (ret == -1){
   
                perror("truncate");
                return -1;
        }
        return 0;
}

可以看到多出来的内容就全部被截断了,只留下长度为10的内容。

六、rename函数

这个函数是将文件进行改名的函数,函数原型如下:

#include <stdio.h>
int rename(const char* oldpath, const char* newpath);
功能:把oldpath的文件名改成newpath
参数:
      oldpath:旧文件名
    newpath:新文件名
返回值:
    成功:0
    失败:-1

总结

这些函数都是比较简单的,大家多练习就可以熟练掌握。
这个网站是我搬运我CSDNsha上的,其实是为了拿个礼品所以搬运的,大家可以看看CSDN上的:https://blog.csdn.net/zagzag001/article/details/130501131

目录
相关文章
|
1月前
|
Linux
关于Linux目录访问函数总结
关于Linux目录访问函数总结
14 1
|
2月前
|
Linux
【Linux 系统编程】wait函数详解
【Linux 系统编程】wait函数详解
26 0
|
2月前
|
存储 算法 Linux
【Linux系统编程】深入理解Linux目录扫描函数:scandir目录函数(按条件扫描目录
【Linux系统编程】深入理解Linux目录扫描函数:scandir目录函数(按条件扫描目录
76 0
|
1月前
|
Java Linux Shell
【Linux】13. 文件操作
【Linux】13. 文件操作
42 1
|
2月前
|
算法 Linux C语言
【Linux系统编程】深入理解Linux目录操作:文件夹位置指针操作函数(telldir,seekdir,rewinddir)
【Linux系统编程】深入理解Linux目录操作:文件夹位置指针操作函数(telldir,seekdir,rewinddir)
25 0
|
2天前
|
Linux
linux中wait与waitpid函数使用场景及扩展
linux中wait与waitpid函数使用场景及扩展
|
5天前
|
Linux C语言
【Linux】 拿下 系统 基础文件操作!!!
怎么样,我们的猜测没有问题!!!所以语言层的文件操作函数,本质底层是对系统调用的封装!通过不同标志位的封装来体现w r a+等不同打开类型! 我们在使用文件操作时,一般都要使用语言层的系统调用,来保证代码的可移植性。因为不同系统的系统调用可以会不一样!
15 2
|
6天前
|
存储 算法 网络协议
【探索Linux】P.26(网络编程套接字基本概念—— socket编程接口 | socket编程接口相关函数详细介绍 )
【探索Linux】P.26(网络编程套接字基本概念—— socket编程接口 | socket编程接口相关函数详细介绍 )
12 0
|
6天前
|
消息中间件 Unix Linux
【探索Linux】P.14(进程间通信 | 匿名管道 | |进程池 | pipe() 函数 | mkfifo() 函数)
【探索Linux】P.14(进程间通信 | 匿名管道 | |进程池 | pipe() 函数 | mkfifo() 函数)
17 0