0723------Linux基础----------文件 IO之文件的打开

1.文件的打开 

  1.1 open 和 fopen 。open 返回的是文件描述符,而fopen 返回的是文件指针,二者的第二个参数也不同,一个是宏定义的,一个是字符串。因此在书写的时候要特别注意。

  int fd = open("test.txt", O_RDONLY);
  FILE *fp = fopen("test.txt", "r");

  1.2 FILE * 和 fd 之间的转化

    1.2.1 从FILE *  转化成 fd。 fileno函数用于将一个文件指针转化成文件描述符,此时就可以使用linux的函数。

 FILE *fp = fopen("test.txt", "r");
 int fd = fileno(fp);  

    1.2.2 从fd 转化成 FILE * 。 fdopen函数用于将一个文件描述符转化成指针,此时就可以使用标准的文件函数。这里fp文件指针的打开模式要和fd文件描述符的打开模式吻合,即只读都是只读。

int fd = open("test.txt", O_RDONLY);
FILE *fp = fdopen(fd, "r");

  1.3 常用的open标志组合:

    a) O_RDONLY:代表只读

    b) O_WRONLY | O_CREAT:以只写方式打开,文件不存在则创建;

    c) O_WRONLY | O_CREAT | O_APPEND:只写打开,文件不存在则创建,文件存在则进行追加;

    d) O_WRONLY | O_CREAT | O_TRUNC:只写打开,不存在则创建,文件存在则清空;

    e) O_WRONLY | O_CREAT | O_EXCL:只写打开,不存在则创建,文件存在则打开失败。

  1.4 文件指针 stdin, stdout,stderr 在内部一定是调用了STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO这三个文件描述符(因为linux底层是用文件描述符实现的)。

2.进程打开一个文件描述符涉及到的数据结构

  2.1 Linux进程打开一个文件描述符,涉及到三个数据结构:

    a)  进程表项,归单个进程所有,记录该进程打开的所有的文件描述符。

    b)  文件表项由内核管理,可对应一次打开文件操作,里面记录打开文件的标志、文件偏移量以及指向文件的指针,以及该结构的引用计数(此时有多少个fd指向它)。

    c)  V节点项,每项对应一个文件,记录着该文件的信息(大小、创建时间、修改时间、所有者、权限)。

  2.2 打开文件时三个数据结构的不同情形:

    a) 一个进程打开两个不同的文件,进程表项 1 个,文件表项 2 个,V结点 2 个;

    b) 一个进程两次打开同一个文件,进程表项 1 个,文件表项 2 个(二者不共享文件偏移量,因此读写不会干扰),V结点 1 个;

    c) 两个进程打开同一文件,进程表项 2 个, 文件表项 2 个, V结点 1 个;

    d) 一个进程打开一个文件,然后用dup 复制了一个文件描述符,此时,进程表项 1 个, 文件表项 1 个(其中引用计数为 2,这与fork一个子进程相同), V结点 1 个。

3.lseek函数

  3.1 lseek 函数用于为一个打开的文件设置当前文件偏移量, 这个当前文件偏移量属性存在于文件表项里面,每一个打开的文件描述符都和一个当前文件偏移量相关联。本例用于返回当前偏移量的值。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define ERR_EXIT(m)     do {         perror(m);        exit(EXIT_FAILURE);    }while(0)
/*
 * lseek 函数
 *
 */

int main(int argc, const char *argv[])
{
    int fd = open("test.txt", O_RDONLY);
    if(fd == -1){
        ERR_EXIT("open");
    }
    char buf[1024] = {0};
    read(fd, buf, 5);
    printf("buf: %s\n", buf);

    //设置文件的偏移量 该偏移量存在于 文件表项中
    //返回当前偏移量距离文件头的字节数
    //这里相当于 获取当前的 文件偏移量
    off_t len = lseek(fd, 0, SEEK_CUR);
    printf("offset = %d\n", (int)len);

    return 0;
}

  3.2 文件通常的读写操作都是从当前文件偏移量开始的。本例中,先将打开的文件的偏移量设置为后移6个字节的值,那么接下来read的时候就从开始当前文件偏移量处(本例中为6)读取。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define ERR_EXIT(m)     do {         perror(m);        exit(EXIT_FAILURE);    }while(0)
/*
 * lseek 函数
 *
 */

int main(int argc, const char *argv[])
{
    int fd = open("test.txt", O_RDONLY);
    if(fd == -1){
        ERR_EXIT("open");
    }
    off_t len = lseek(fd, 6, SEEK_CUR); //将当前的偏移量设置为 当前偏移量+6
    printf("offset = %d\n", (int)len);

    char buf[1024] = {0};
    read(fd, buf, 5);
    printf("buf: %s\n", buf);

    len = lseek(fd, 0, SEEK_CUR);
    printf("offset = %d\n", (int)len);
    return 0;
}

  3.3 lseek 还可以获取文件的大小。这里用 od -c filename 查看文件的内容 可以看到文件的大小,注意左边的是8进制。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define ERR_EXIT(m)     do {         perror(m);        exit(EXIT_FAILURE);    }while(0)
/*
 * lseek 函数
 * 获取文件的大小
 */

int main(int argc, const char *argv[])
{
    int fd = open("test.txt", O_RDONLY);
    if(fd == -1){
        ERR_EXIT("open");
    }
    off_t len = lseek(fd, 0, SEEK_END);// 设置偏移量为 SEEK_END
    printf("offset = %d\n", (int)len);

    return 0;
}

  

  3.4 lseek 设置文件偏移量时,如果当前没有数据,就写0。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define ERR_EXIT(m)     do {         perror(m);        exit(EXIT_FAILURE);    }while(0)
/*
 */

int main(int argc, const char *argv[])
{
    int fd = open("test.txt", O_WRONLY | O_CREAT | O_TRUNC);
    if(fd == -1){
        ERR_EXIT("open");
    }
    write(fd, "hello", strlen("hello"));

    off_t len = lseek(fd, 10, SEEK_CUR);
    printf("offset = %d\n", (int)len);

    write(fd, "world", strlen("world"));

    close(fd);
    return 0;
}

  

  3.5 文件空洞

    3.5.1 什么是文件空洞? 当文件偏移量超过文件大小的时候,就产生了文件空洞,它被记录在文件信息中,但是在磁盘上并不占据过多地的磁盘空间。例如我们在文件中偏移1G的大小,那么在文件信息中就记录了 1G 的空洞,但是在磁盘上并不占据实际空间,如下图所示。

    3.5.2 程序示例和程序运行后的文件信息和磁盘信息。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define ERR_EXIT(m)     do {         perror(m);        exit(EXIT_FAILURE);    }while(0)
/*
 * 文件空洞
 *
 */

int main(int argc, const char *argv[])
{
    int fd = open("test.txt", O_WRONLY | O_CREAT | O_TRUNC);
    if(fd == -1){
        ERR_EXIT("open");
    }
    char buf[] = "hello";
    write(fd, buf, strlen(buf));

    off_t len = lseek(fd, 1024*1024*1024, SEEK_CUR);
    printf("OFF_SET = %d\n", (int)len);

    write(fd, "world", strlen("world"));

    close(fd);

 

  

0723------Linux基础----------文件 IO之文件的打开

时间: 2024-08-12 20:52:34

0723------Linux基础----------文件 IO之文件的打开的相关文章

Linux 基础入门----用户及文件权限管理

用户及文件权限管理 实验介绍 1.Linux 中创建.删除用户,及用户组等操作. 2.Linux 中的文件权限设置. 一.Linux 用户管理 Linux 是一个可以实现多用户登陆的操作系统,比如“李雷”和“韩梅梅”都可以同时登陆同一台主机,他们共享一些主机的资源,但他们也分别有自己的用户空间,用于存放各自的文件.但实际上他们的文件都是放在同一个物理磁盘上的甚至同一个逻辑分区或者目录里,但是由于 Linux 的 用户管理 和 权限机制 ,不同用户不可以轻易地查看.修改彼此的文件. 下面我们就来学

Linux基础命令,目录文件操作,vi编辑器详解

一.linux基础命令 linux命令的执行必须依赖于shell命令解释器.shell实际上是在linux系统中运行的一种特殊程序,它位于操作系统内核与用户之间,负责接收用户输入的命令并进行解释,将需要执行的操作传递给系统内核执行,shell在用户和内核之间充当了一个"翻译官"的角色.当用户登录到linux系统时,会自动加载一个shell程序,以便给用户提供可以输入命令的操作系统. 1.首先介绍一下快捷键 Tab键:用来补齐命令字或文件.目录名,例如输入"ifcon"

Linux基础篇三——链接文件知多少

As is known to all,在windows环境下我们早已经见过链接文件,机我们平时所使用的快捷方式. 其实,在linux里我们可以见到以下两种类型的链接文件 a.硬链接文件 创建命令:ln [源文件] [目标文件] 硬链接即实际链接. 记得我们讲过什么叫做inode,那么我们来根据下图理解一    这样做的意义是:安全.如果你不慎删除了其中一个文件名那么你还可以通过其他文件来找到这个源文件 并且你修改一个文件其他的文件也会跟着被修改 *上图中能看到,这两个文件的信息是一模一样的 实际

Linux基础入门--find(文件查找)

文件查找:在文件系统上查找符合条件的文件,条件是自己给出 Linux系统上实现工具:locate,find locate: 依赖于实现构建好的索引库,系统自动实现,一旦文件发生变化需要一定的周期时间更新.也可以手动更新数据.在索引构建过程中需要遍历整个文件系统,极消耗资源. 工作特点: 1.查询速度快 2.模糊查找 3.非实时查找 locate不能实时查找因此就到此为止 ============================================================ fi

Linux基础(15)文件访问控制列表

当需要为某个特定用户设定对于某个文件的权限的时候,传统的chmod操作可能无法满足我们的需要,这个时候可以使用facl(file access control system)文件访问控制列表为文件针对某个用户设定额外的权限,与此相关的命令有两个,serfacl,getfacl. 1.setfacl 设定权限. 用法: setfacl -m u:username:perm file... 为用户设定权限 setfacl -m g:groupname:perm file...为组设定权限 例子: s

linux[基础]-20-用户与文件权限-[文件特殊权限]-[01]

用户与文件权限 用户: 用户root是系统的超级管理员,而真正让他成为管理员的不是 用户名"root",而是其UID编号. UID:每个用户都有相对应的UID号,就像我们的身份证号一样 超级用户:UID为0也就是root用户 系统用户:UID 1~999 系统服务的用户,默认被限制登录系统 普通用户:UID 1000~ 管理员创建的用户不能管理系统的用户 帐户名称与UID存放在/etc/passwd文件 密码存放在/etc/shadow文件 GID:用户组的编号,方便授权指派工作 每个

一天一个linux基础命令之查看文件类型file

file 查看文件类型 1.命令格式 file [options]  FILE ... 2.命令功能 该命令用来识别文件类型,也可用来辨别一些文件的编码格式.它是通过查看文件的头部信息来获取文件类型. 3.常用参数 -b:只列出文件辨识结果,不显示文件名称. -f:查看文件中的文件名的文件类型,一般用于shell编程 -i:以mime类型来显示文件的类型 -z:尝试去解读压缩文件的内容 -F:使用指定分隔符号替换输出文件名后的默认的":"分隔符. -L:查看对应软链接对应文件的文件类型

Linux基础之IO重定向及管道详解(涉及tr、tee命令)

我在刚开始接触IO重定向时,经历了由懂到不懂然后了然的过程,当然现在的我也不可能说对于IO重定向就彻底懂了,只是在解决一些问题或实现某些结果时不会因为IO重定向的问题而迷惑了.     什么叫IO重定向? 为了解释这个问题,我们要先明白什么叫IO,什么叫做程序的数据流. 什么叫IO? 在Linux或计算机领域IO指的是信息的输入和输出. 在Linux中可用于输入的设备:文件(Linux中一切皆文件) 具体包括:键盘设备.文件系统上的常规文件.网卡等. 在Linux中用于输出的设备:文件 具体包括

一天一个linux基础命令之修改文件时间戳touch

touch  修改时间戳(常用于创建空文件) 1.命令格式 touch [options]File ... 2.命令功能 用于修改文件的时间戳.访问时间.修改时间.改变时间.如果什么参数也不加默认创建一个空文件 Linux文件时间戳(timestamp): 访问时间:最近一次被访问(被读) access 修改时间:写数据  modify 改变的文件的内容 改变时间:改变元数据(文件的属性)  change,metadata,元数据  改变的文件的属性 改变时间会自动变化,当文件访问时,或者修改文