Linux C语言 学习之 IO操作

        文件I/O 又称为低级磁盘I/O,遵循POSIX相关标准。任何兼容POSIX标准的操作系统上都支持文件I/O。标准I/O被称为高级磁盘I/O,遵循ANSI C相关标准。只要开发环境中有标准I/O库,标准I/O就可以使用。(Linux 中使用的是GLIBC,它是标准C库的超集。不仅包含ANSI C中定义的函数,还包括POSIX标准中定义的函数。因此,Linux 下既可以使用标准I/O,也可以使用文件I/O)。

        通过文件I/O读写文件时,每次操作都会执行相关系统调用。这样处理的好处是直接读写实际文件,坏处是频繁的系统调用会增加系统开销,标准I/O可以看成是在文件I/O的基础上封装了缓冲机制。先读写缓冲区,必要时再访问实际文件,从而减少了系统调用的次数。

        文件I/O中用文件描述符表现一个打开的文件,可以访问不同类型的文件如普通文件、设备文件和管道文件等。而标准I/O中用FILE(流)表示一个打开的文件,通常只用来访问普通文件。

 

标准IO

stdin : 标准输入

stdout : 标准输出

stderr : 标准错误

文本文件和二进制文件区别:存储格式不同,文本文件只能存储文本。

1. fopen()

占用资源;调用fopen()函数可以打开或创建一个文件。

FILE *fopen(const char *path, const char *mode);

path : 参数 path 指向文件路径,可以是绝对路径、也可以是相对路径。当前路径不需要加目录,别的路径要加目录

mode : 参数 mode 指定了对该文件的读写权限,是一个字符串。

  • "r":打开只读文件,该文件必须存在。
  • "r+":打开可读写的文件,该文件必须存在。
  • "w":打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。
  • "w+":打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。
  • "a":以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。
  • "a+":以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。

2. fclose()

释放资源;关闭一个由 fopen() 打开的文件。

int fclose(FILE *stream);

3. fread()

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

ptr:将读取到的数据存放在参数 ptr 指向的缓冲区中;(读的内容)

size:读取 nmemb 个数据项,每一个数据项的大小为 size 个字节(读的大小)

nmemb:参数 nmemb 指定了读取数据项的个数。(读多少个)

返回值:实际读取的个数,小于等于nmemb

4. fwrite()

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

ptr:将参数 ptr 指向的缓冲区中的数据写入到文件中。(写的内容)

size:参数 size 指定了每个数据项的字节大小(写的大小)

nmemb:参数 nmemb 指定了写入的数据项个数(写的个数)

5. fgetc()

每次读一个字符

int fgetc(FILE *stream);

6. fputc()

每次写一个字符

int fputc(int c, FILE *stream);

7. fgets()

每次读一行的字符串

char *fgets(char *s, int size, FILE *stream);

从stream中最多读入一个小于size的字符,最大读取字符为size-1,并将它们存储到指向的内存s中 , 读取在EOF或换行符(\n)之后停止。如果读取了换行符,则将其存储到缓冲区中。使用(‘\0’)存储在缓冲区的最后一个字符之后。fgets遇到\n 停止读入, ‘\n’会被读取进来, 保存到s中, 最后会加上一个’\0’, 做为字符串结束标志

8. fputs()

每次写一行的字符串

int fputs(const char *s, FILE *stream);

9. ftell()

获取文件位置

long ftell(FILE *stream);

10. fseek()

设置文件的位置(定位)

int fseek(FILE *stream, long offset, int whence);

offset:基于 whence 的偏移量, 以字节计算偏移量

whence:

  • SEEK_SET : 设置文件指定的位置
  • SEEK_CUR : 基于当前的文件位置
  • SEEK_END : 基于文件末尾的位置

11. fflush()

强制刷新缓存

int fflush(FILE *stream);

12. fcntl()

  fcntl() 针对(文件)描述符提供控制。

  int fcntl(int fd, int cmd);

  int fcntl(int fd, int cmd, long arg);

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

  参数 fd 是被参数 cmd 操作的描述符。针对 cmd 的值,fcntl 能够接受第三个参数 int arg。

  返回值与命令有关。如果出错,所有命令都返回-1,如果成功则返回某个其他值。

下列三个命令有特定返回值:F_DUPFD、F_GETFD、F_GETFL 以及 F_GETOWN。

  •   F_DUPFD 返回新的文件描述符
  •   F_GETFD 返回相应标志
  •   F_GETFL、F_GETOWN 返回一个正的进程 ID 或负的进程组 ID 。

  复制一个现有的描述符(cmd = F_DUPFD)。

  获得/设置文件描述符标记(cmd = F_GETFD 或 F_SETFD)。

  获得/设置文件状态标记(cmd = F_GETFL 或 F_SETFL)。

  获得/设置异步I/O所有权(cmd = F_GETOWN 或 F_SETOWN)。

  获得/设置记录锁(cmd = F_GETLK、F_SETLK 或 F_SETLKW)。

文件IO

        文件描述符:对于内核而言,所有打开的文件(Linux 中一切皆文件)都由一个文件描述符标识。文件描述符是一个非负整数。当打开一个现存文件或创建一个新文件时,内核向进程返回一个文件描述符。

非负整数。从0开始,依次递增 最多1024个文件: 0-1023

0标准输入 1标准输出 2错误输出

1. open

打开一个已经存在的文件

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

  • O_APPEND :以追加方式打开文件,每次写时都写在文件末尾。
  • O_CREAT :如果文件不存在,则创建一个,存在则打开它。
  • O_EXCL 与O_CREAT:一起使用时,如果文件已经存在则返回出错。
  • O_TRUNC :以只写或读写方式打开时,把文件截断为0
  • O_DSYNC :每次write时,等待数据写到磁盘上。
  • O_RSYNC :每次读时,等待相同部分先写到磁盘上。
  • O_NONBLOCK :对于设备文件,以O_NONBLOCK方式打开可以做非阻塞I/O(Nonblock I/O)
  • O_SYNC: 每次write时,等到数据写到磁盘上并接更新文件属性。
rO_RDONLY
r+O_RDWR
wO_WRONLY | O_CREAT | O_TRUNC, 0664
w+O_RDWR | O_CREAT | O_TRUNC, 0664
aO_WRONLY | O_CREAT | O_APPEND, 0664
a+O_RDWR | O_CREAT | O_APPEND, 0664

创建一个新的文件(不能创建设备文件)

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

文件最终权限 = 写入权限 - umask

umask:设定文件或者目录的初始权限

2. close

close 关闭已经打开的文件,并释放文件描述符

int close(int fd)

3. read

从打开的设备或文件偏移量处读入指定大小的数据。

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

        读常规文件是不会阻塞的,不管读多少字节,read一定会在有限的时间内返回。

        从终端设备或网络读则不一定,如果从终端输入的数据没有换行符,调用read读终端设备就会阻塞,如果网络上没有接收到数据包,调用read从网络读就会阻塞,至于会阻塞多长时间也是不确定的,如果一直没有数据到达就一直阻塞在那里。同样,写常规文件是不会阻塞的,而向终端设备或网络写则不一定。

4. write

向打开的设备或文件中写入一定字节的数据。

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

5. lseek

用来定位当前文件偏移量

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

whence:

  • SEEK_SET:读写偏移量将指向 offset 字节位置处(从文件头部开始算);
  • SEEK_CUR:读写偏移量将指向当前位置偏移量 + offset 字节位置处,offset 可以为正、也可以为负,如果是正数表示往后偏移,如果是负数则表示往前偏移;
  • SEEK_END:读写偏移量将指向文件末尾 + offset 字节位置处,同样 offset 可以为正、也可以为负,如果是正数表示往后偏移、如果是负数则表示往前偏移。

目录

1. opendir

打开一个目录

DIR *opendir(const char *name);

2. readdir

成功则返回下个目录进入点,返回本目录位置指针所指的文件并以结构体的方式返回. 有错误发生或读取到目录文件尾则返回NUL

struct dirent *readdir(DIR *dirp);

struct dirent {

        ino_t d_ino; 文件的inode

        off_t d_off; 目录文件开头至此目录进入点的位移

        signed short int d_reclen;的长度, 不包含NULL 字符

        unsigned char d_type; 所指的文件类型 d_name 文件名

        char d_name[256]; };

3. closedir

关闭目录文件

int closedir(DIR *dirp);

  • 10
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丶小破孩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值