欢迎光临
我们一直在努力

Linux应用软件编程|Linux文件操作(标准IO详解)

前言

在Linux C开发中,文件操作是基本功,分为标准IO(C库函数)和文件IO(系统调用)。本文重点讲解标准IO,标准IO是C标准库封装好的接口,移植性强,内部自带缓冲区。

内存读写速度快,但程序退出或者断电数据直接丢失;硬盘上的文件可以持久保存数据,但是读写速度慢。我们开发中经常需要通过文件完成数据持久化。

内存:速度快、断电丢失、空间小;

文件(外存硬盘):速度慢、断电保存、存储空间大。

Linux哲学:一切皆文件,普通文本、硬件设备、管道、套接字全部抽象成文件来操作。

一、Linux七种文件类型

使用命令 ls -l 文件名 可以查看文件的属性信息,第一位字符代表文件类型,Linux一共7种文件类型:

标识

文件类型

说明

b

块设备文件

硬盘、SD 卡等存储设备

c

字符设备文件

鼠标、键盘、显示器,按字节流访问硬件

d

目录文件

对应文件夹

普通文件

.c.txt、可执行程序 a.out、图片视频

l

软连接文件

类似 Windows 快捷方式(符号链接)

s

套接字 socket 文件

用于本地进程间、网络编程

p

管道文件

进程间通信使用

 二、IO分类:标准IO vs 文件IO

IO全称Input/Output输入输出。

1. 标准IO:属于C标准库函数,头文件<stdio.h>,例如printf`、scanf`、fopen,可跨平台移植,自带用户态缓冲区。

2. 文件IO:Linux内核提供系统调用,属于操作系统接口,只在Linux/Unix下使用,没有用户缓冲区。

man手册使用小技巧

man 1 xxx:查看Linux命令

man 2 xxx:查看系统调用(open等)

man 3 xxx:查看C库函数(fopen等)

标准IO操作流程

打开文件 → 读/写文件 → 关闭文件

上图:标准IO读写流程,程序通过FILE文件流指针,在内存缓冲区和硬盘文件之间交互。

FILE* 文件流指针

标准IO所有操作都是围绕`FILE*`文件流指针,FILE结构体内部维护缓冲区、文件状态等信息。

Linux程序启动,系统默认帮我们打开3个流,无需手动fopen:

流指针

含义

对应设备

stdin

标准输入流

键盘

stdout

标准输出流

终端显示屏

stderr

标准错误流

终端显示屏

示例:putchar('a');等价于 fputc('a', stdout);

三、标准IO核心API详解

1. fopen 打开文件

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

功能:打开文件,返回文件流指针

pathname:文件路径+文件名

mode:打开模式

mode

作用

"r"

只读,文件必须存在,否则打开失败

"r+"

读写打开,文件必须存在

"w"

只写;不存在就创建;文件存在直接清空原有内容

"w+"

读写;不存在创建;存在清空文件

"a"

追加只写;不存在创建;写数据永远在文件末尾

"a+"

读写;不存在创建;读从文件开头,写只能追加到末尾

返回值:成功返回FILE*指针;失败返回NULL,一定要做判空处理。

 2. fclose 关闭文件

int fclose(FILE *stream);

功能:关闭已经打开的文件流

重要:打开的文件必须关闭,否则产生**文件描述符泄露**,耗尽系统资源。

返回:成功返回0;失败返回`EOF(-1)`

3. fputc:写入单个字符

int fputc(int c, FILE *stream);

 c:要写入字符的ASCII码

stream:文件流指针

返回:成功返回写入字符;失败返回`EOF(-1)`

 4. fgetc:读取单个字符

int fgetc(FILE *stream);

从文件读取一个字符;读到文件末尾或者出错返回`EOF(-1)`。

#include <stdio.h>

int main(int argc, const char *argv[])

{

    // 判断命令行参数个数

    if (argc < 3)

    {

        printf("Usage: ./a.out srcfile dstfile\\n");

        return -1;

    }

    FILE *fpsrc = fopen(argv[1], "r");

    FILE *fpdst = fopen(argv[2], "w");

    if (NULL == fpsrc || NULL == fpdst)

    {

        printf("fopen error\\n");

        return -1;

    }

    int ret = 0;

    while(1)

    {

        ret = fgetc(fpsrc);

        if(EOF == ret)

            break;

        fputc(ret, fpdst);

    }

    fclose(fpsrc);

    fclose(fpdst);

    return 0;

}

编译运行:./a.out test.txt bak.txt,就可以完成文件拷贝。

 补充:main函数命令行参数

int main(int argc, const char *argv[])

argc:argument count,命令行参数总个数

argv:argument vector,字符串指针数组,保存每一个参数字符串

示例执行命令:./mycp 1.txt 2.txt

argc = 3

argv[0] = "./mycp"    程序本身名字

argv[1] = "1.txt"     源文件

argv[2] = "2.txt"     目标文件

注意:argv[0]永远代表程序名。

5. fputs 写字符串

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

将字符串写入文件,不会写入字符串结束符`'\\0'`**。

返回:成功返回大于等于0;失败返回EOF。

 查看文件原始内容命令:od -c filename,以字符格式打印文件十六进制内容。

 6. fgets 读取一行字符串

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

s:读取出来数据存放的缓冲区

size:期望读取字节,**最多读取size1个字节,末尾自动补'\\0'**

遇到换行符`\\n`就结束一行读取;到达文件末尾返回NULL。

注意:fgets会把文件中的换行符`\\n`一并读到缓冲区。

四、易错点总结

1. fopen一定要判断返回NULL,防止打开失败;

2. fopen打开后必须配对fclose,防止文件描述符泄露;

3. "w"/"w+"模式打开会直接清空文件,开发不要误操作;

4. a+模式读从文件开头,写只能追加在末尾;

5. fgets最多读size1字节,会自动预留位置存放`\\0`;

6. EOF值为1,fgetc接收返回值变量要用int类型,不要用char。

赞(0)
未经允许不得转载:171主机测评 » Linux应用软件编程|Linux文件操作(标准IO详解)
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址