Linux 应用软件编程 文件编程(IO)

常见的操作系统:

1.Windows:界面友好,使用方便。闭源收费。pc

2.Linux:类Unix,开源免费。嵌入式平台

2.Unix:收费

4.FreeRTOS:小型嵌入式平台,实时性

一、文件编程(IO)

IO:input/output 输入/输出

1.为什么学习文件操作

1.保存数据,掉电数据不丢失,保存在硬盘(外存)

2.一切皆文件(硬盘、鼠标、键盘、显示器、普通文件....)

2. Linux下的文件类型

ls -l 查看Linux下的文件相关详情(ll)

cpp 复制代码
d       rwx rwx r-x                    2        linux   linux  4096 11月  5  2024 serial
文件类型 文件读写可执行权限              硬链接个数   用户自己  组长   文件大小  文件最后被修改的时间
         rwx:自己对文件的读写可执行权限
         rwx:同组用户对文件的读写可执行权限
         rwx:其他人
cpp 复制代码
b c d - l s p七种文件类型 *
b  ---block          ---块设备文件(硬盘)
c  ---character      ---字符设备文件(鼠标、键盘、显示器、外设传感器...)
d  ---directory      ---目录文件(文件夹)
-  ---regular        ---普通文件(xxx.c  xxx.h  a.out xxx.jpg...)
l  ---link           ---链接文件(类似于快捷方式)
s  ---socket         ---套接字文件(网络通信)
p  ---pipe           ---管道文件(进程间通信)

3. 文件操作方法

Linux下的两种文件操作方式:

标准IO:C标准库提供的对文件的操作接口(库函数)如printf、scanf

文件IO:Linux内核提供的对文件的操作方法(系统调用)

文件操作思想:

1.打开文件

2.读写文件

3.关闭文件

4. 标准IO

学习标准C库提供的一堆对文件的操作接口(函数)-----》通过man手册

1.打开文件:fopen

2.读写文件:fgetc/fputc、fgets/fputs、fread/fwrite

3.关闭文件:fclose

cpp 复制代码
    man手册
	标准man手册分为8个章节:
	man 1        用户命令
	man 2        系统调用
	man 3        c函数库调用
	man 4        设备文件和特殊文件
	man 5        配置文件和格式
	man 6        游戏相关
	man 7        杂项,总述
	man 8        管理类命令

函数接口:

1. fopen
cpp 复制代码
FILE *fopen(const char *pathname, const char *mode);
功能:打开一个文件,并获得一个文件流指针
参数:
	pathname:文件名
	mode:文件的打开方式
	"r"  以只读方式打开,文件必须存在
	"r+" 以读写方式打开,文件必须存在
	"W"  以只写方式打开,文件存在则清空,文件不存在则创建
	"w+" 以读写方式打开,文件存在则清空,文件不存在则创建
	"a"  以追加写的方式打开,文件不存在则创建
	"a+" 以读和追加写的方式打开,文件不存在则创建
返回值:
    成功:返回文件流指针FILE *
    失败:NULL

文件流:从文件中读写数据时体现出来的字节流。文件流指针:FILE*。

标志IO中对文件的操作都是面向文件流指针。

2. fclose
cpp 复制代码
int fclose(FILE *stream);
功能:关闭文件
参数:
     stream:已打开的文件的文件流指针
返回值:
     成功:0
     失败:EOF(-1)
3. fputc
cpp 复制代码
int fputc(int c, FILE *stream);
功能:向文件中写入一个字符
参数:
    c : 要写入的字符的ASCII值
    stream:要写入的文件流指针
返回值:
    成功:写入的字符的ASCII值
    失败:EOF(-1)

练习:1. 使用fputc向文件中写入"hello world"

od -c 文本文件名 :以字符方式查看该文件中的数据

cpp 复制代码
int main()
{
    FILE*fp = fopen("1.txt","w+");
    if(fp == NULL)
    {
        printf("fopen malloc\n");
    }

    char a[12] = "hello world";
    int len = strlen(a);
    for(int i = 0;i<len;i++)
    {
        
        fputc(a[i],fp);
    }
    fclose(fp);

    return 0;
}
4. fgetc
cpp 复制代码
int fgetc(FILE *stream);
功能:从文件中读取一个字符
参数:
     stream:文件流指针
返回值:
    成功:读到的字符的ASCII值
    失败:EOF(-1)
    读到文件末尾:EOF

练习:

使用fgetc实现cat的功能,将一个指定的文本文件内容输出到终端。

cpp 复制代码
#include<stdio.h>
int main(int argc,char*argv[])
{
    if(argc < 2)
    {
        printf("usage:./a.out <filename>\n");
        return -1;
    }


    FILE*fp = fopen(argv[1],"r");
    if(fp == NULL)
    {
        printf("fopen error");
        return -1;
    }
    int ret = 0;
    while(1)
    {
        ret = fgetc(fp);
        if(ret == EOF)
        {
            break;
        }
         printf("%c",ret);
    }

    fclose(fp);
    return 0;
}

使用fgetc和fputc实现文件的拷贝,使用主函数传参的方式实现。

cpp 复制代码
int copy_file(const char*srcname,const char*dstname)
{
    FILE*fpsrc = fopen(srcname,"r");
    FILE*fpdst = fopen(dstname,"w");
    
    if(fpsrc == NULL || fpdst == NULL)
    {
        printf("fopen error\n");
        return -1;
    }

    char str = 0;
    while(1)
    {
        str = fgetc(fpsrc);
        if(str == EOF)
        {
            break;
        }
        fputc(str,fpdst);
    }
    fclose(fpsrc);
    fclose(fpdst);

}
int main(int argc,char*argv[])
{
    if(argc < 2)
    {
        printf("usage <srcname> <dstname>\n");
        return -1;
    }
    
    copy_file(argv[1],argv[2]);
    
   
    return 0;
}

三个操作系统已经打开的文件流:stdin stdout stderr

cpp 复制代码
三个操作系统已经打开的文件流:
FILE *
stdin   --->标准输入流---》关联的文件:输入设备:键盘
stdout  --->标准输出流---》关联的文件:输出设备:显示屏
stderr  --->标准出错流---》关联的文件:显示屏

fgetc和getchar:ret = getchar() ====>ret = fgetc(stdin);

fputc和putchar:putchar(ret) =====>fputc(ret, stdout);

5. fgets
cpp 复制代码
char *fgets(char *s, int size, FILE *stream);
功能:从文件中读取一行
参数:
    s:存放读取数据的内存首地址
    size:希望从文件中读到的字节数
    stream:要读的文件的文件流指针
返回值:
	成功:返回s的地址
	失败:NULL
	读到文件末尾:NULL

实现cat的功能

gets和fgets的区别

gets只能从终端读取数据;fgets可以任意文件流指针中读取

fgets会保留用户收入的\n字符,gets不会读取\n字符

fgets安全的,gets是危险的:fgets最多读取size-1个数据,最后一个位置存放字符串结束标志;

gets没有大学的限制

6. fputs
cpp 复制代码
int fputs(const char *s, FILE *stream);
功能:向文件中写入一行数据
参数:
    s :要写入的数据的首地址
    stream:要写入的文件
返回值:
	成功:>0
	失败:EOF(-1)
注意:不会将字符串结束标志'\0'字符写入文件
        fgets和fputs不能处理二进制文件,

练习:

利用fgets和fputs实现文件拷贝

cpp 复制代码
#include<stdio.h>

    int file_copy(const char*srcname,const char*dstname)
    {

        FILE*fpsrc = fopen(srcname,"r");
        FILE*fpdst = fopen(dstname,"w");
        if(NULL == fpsrc || NULL == fpdst)
        {
            printf("fopen error\n");
            return -1;
        }
         
        while(1)
        {
            char buff[128] = {0};
            char*p = fgets(buff,sizeof(buff),fpsrc);
            if(NULL == p)
            {
                break;
            }
            fputs(buff,fpdst);
        }
        fclose(fpsrc);
        fclose(fpdst);
        
        return 0;
    }
int main(int argc,char*argv[])
{
    if(argc < 3)
    {
        printf("usage ./a.out srcname dstname\n");
        return -1;
    }
    file_copy(argv[1],argv[2]);
    
    
    return 0;
}

统计文件中各种字符个数

cpp 复制代码
#include<stdio.h>

int main(int argc,char*argv[])
{
    if(argc < 2)
    {
        printf("usage:./a.out filename\n");
        return -1;
    }

    int cnt[256] = {0};
    FILE*fp = fopen(argv[1],"r");

    if(NULL == fp)
    {
        printf("fopen error\n");
        return -1;
    }
    int ret = 0;
    while(1)
    {
        ret = fgetc(fp);
        if(EOF == ret)
        {
            break;
        }
        cnt[ret]++;
    }
    int sum = 0;
    for(int i = 0;i<256;i++)
    {
        if(cnt[i]!= 0)
        {
            printf("%c : %d is %d\n",i,i,cnt[i]);
        }
    }
    fclose(fp);

    return 0;
}

结果:

其他

1.主函数传参

程序运行时,命令行传递的参数可通过主函数传参的方式,传递给程序。

实参:命令行参数

形参:int main(int argc, const char *argv\[\])

argc:命令行传递的参数个数 argv:指针数组:多个指针,分别指向命令行传递的参数

cpp 复制代码
./a.out aaa bbb
argv[0] : ./a.out
argv[1] : aaa
argv[2] : bbb

2.const修饰的指针

cpp 复制代码
    const char *p;     ---->const修饰p指向的内容,表示该内容只读(不能被修改)
	char const *p;     ---->同上
	char *const p;     ---->const修饰指针p,表示指针的指向不能发生修改
	const char *const p; ---->p指针指向不能被修改,指向的内容也不能被修改

​ 3. 普通文件(-)

​ ASCII文件(文本文件): '2' '0' '2' '6' xxx.c xxx.h xxx.txt

​ 二进制文件:0/1 011111101010 a.out xxx.png xxx.jpg xxx.bmp xxx.mp4

相关推荐
枕星而眠1 小时前
Linux IO多路复用:select、poll、epoll 核心原理与进阶实战
linux·运维·服务器·c++·后端
Rain5091 小时前
GitLab-Runner + AI 代码审查服务 + 远程大模型 全套部署运维实战
linux·运维·人工智能·python·ci/cd·gitlab·ai编程
冷色调的咖啡师1 小时前
4.大数据高可用
大数据·linux·hadoop·hdfs·zookeeper·yarn
Black蜡笔小新1 小时前
零代码自动化企业私有化AI训练推理一体工作站DLTM训推一体化助力企业自主掌控AI能力
运维·人工智能·自动化
jimy11 小时前
Gemini cli搜索文件find、grep的例子
linux·服务器
txg6662 小时前
WildSync:通过Wild API 使用恢复实现自动化 Fuzzing Harness 合成
运维·深度学习·网络安全·自动化
冷色调的咖啡师2 小时前
1.大数据架构技术 上——搭建分布式Hadoop集群
大数据·linux·hadoop·分布式·hdfs·架构·yarn
信创工程师-小杨2 小时前
OpenEuler系统如何升级OpenSSh10.3P1版本
linux·运维·服务器
2601_961194022 小时前
27考研刘晓燕资源
linux·sql·ubuntu·华为·pdf·.net