• 嵌入式学习(标准IO)


    linux应用编程 (高级编程)
    IO
    多任务
    网络

    IO(文件) 

    文件操作:
    文本文件,mp3,jpeg,png ,mp4,avi

    文件:
        一组相关数据的有序集合
    文件名:
        这组相关数据的一个名称

    linux里面对文件的处理:
    思想:
          一切皆文件 ,文件用来存储数据(数据、指令)
          everything is file!
          

    b c d - l p s 

    b -- block      -- 块设备文件   --- 硬盘(存储设备) 
    c -- character  -- 字符设备文件 --- 鼠标 (输入输出设备)
    d -- directory  -- 目录文件     
    - -- regular    -- 普通文件 (分类:二进制文件:.jpg  .bmp  .mp4  a.out
                            ASCLL文件: .txt  .c  .h)
    l -- link       -- 软连接文件   --- 类似windows的快捷方式  
    p -- pipe       -- 管道文件     --- 实现操作系统中 进程间的一些 信息交换(通信)
    s -- socket     -- 套接字文件   --- 网络的时候 (进程间的通信)


    【操作文件的基本思路及框架】//凡是文件,都可从这个思路出发进行思考
    文件操作三步骤:
    1.打开 
    2.读写    
    3.关闭 

    Linux提供的两种文件操作方式:
    文件编程:
    1.标准IO --- 库函数  -------标准c库函数,
    2.文件IO --- 系统调用-------Linux内核为用户提供的函数接口


    系统调用:Linux内核为用户提供的函数接口
    库函数:标准c库函数, 对Linux内核中系统调用的封装
        
        

    标准IO库:
    1.标准io的概念 
        1975 Dennis Ritchie编写, IO库,
        从C语言的标准,ANSI c 
        IO  input  output
        I: 键盘是标准输入设备 ====》默认输入就是指键盘  /dev/input
        O: 显示器是标准输出设备 ==》默认输出就是指显示器
        
        Linux操作系统当中IO都是对文件的操作
        C一部分,任何支持标准C的系统都可使用标准IO实现文件存储
        标准IO在UNIX上是对文件IO的封装
       
        一般都是对普通文件操作是一种有缓存的IO 在文件IO和用户程序之间,
        加入缓冲区,可以有效减少系统调用的次数,节省系统IO调度资源
        


    2.功能:
      用来操作普通文件
          普通文件:
            1.ASCII码文件(代码、文本文件)
            2.二进制文件(音视频、图片)
            
            ASCII码文件是一种特殊的二进制文件
            
            2021
            '2' '0' 2' '1' 
            
            2021
            0000 0000 0000 0000 0000 0111 1110 0101


    3.操作方法
        1.打开 -- fopen  //FILE open
        2.读写 --
                  fgetc / fputc   读出、写入单个字符
                  fgets / fputs   读出、写入一行字符
                  fread / fwrite  读出、写入指定长度数据
        3.关闭 -- fclose          


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

    4.API函数接口
     
        1.fopen
        #include
        FILE* fopen(const char *path, const char *mode);
        功能:
             流打开函数 (打开文件,并关联到一个流)
        参数:
            @pathname --要打开的文件的文件名(字符串形式)
            @mode --打开文件的操作模式
                r ---打开文件做读操作
                     注意:
                     文件必须存在 
                     
                     文件必须存在
                     
                r+   打开文件做写操作
                w   打开文件做读写操作
                     注意:
                     注意:
                     如果文件已经存在,则会将文件清空为0
                     如果文件不存在,则会创建一个新文件。
                     
                w+  打开文件做读写操作
                       如果文件已经存在,则在文件末尾进行写入 
                      如果文件不存在,则会创建一个新文件。
                     
                a+   打开文件做读写操作     
                     注意:
                     如果文件已经存在,则会将文件清空为0
                     如果文件不存在,则会创建一个新文件。

                a    打开文件做写操作
                     注意:
                     注意:
                     如果文件已经存在,则在文件末尾进行写入 
                     如果文件不存在,则会创建一个新文件。
                
                
        返回值:
           成功 FILE *  (文件流指针)
           失败 NULL 并且 设置 errno 表明错误原因 

        od -c 查看ASCLL中的字符
        cat 将文件中字符打印到终端

           
        流:
            数据从文件当中流入和流出所体现出来的字节流叫做流

            FILE 结构定义的对象(FILE * 指向的对象)称之为流对象,FILE *叫文件流指针。


            标准IO将对文件的操作转换成了对"流"的操作。
            所以,标准IO的文件相关的函数都是围绕着 FILE进行的。
             
              FILE * fp 
              FILE * fp;//流指针------关联一个文件   
              FILE * 实际上是指向了一块内存空间(缓存,fileno)
              
              
              FILE *fp <->【FILE结构体[缓存,fileno]】//堆区(malloc)
     
        2.fclose
          int fclose(FILE *fp);
          功能:
            关闭文件流指针 
          参数:
            fp:文件流指针 
          返回值:
            成功返回0 
            失败返回EOF(-1)
            
          注意:fopen操作完毕后使用fclose关闭,否则会产生内存泄漏
               不要重复调用fclose 
     
     
     
    练习:
       用fopen实现一个touch的功能!
           (如何从命令行获取 文件名,然后进行操作)

    1. #include <stdio.h>
    2. int main(void)
    3. {
    4. FILE *fp = NULL;
    5. fp = fopen("1.txt","r+");
    6. if (fp == NULL)
    7. {
    8. printf("没有这个文件!!!\n");
    9. return 0;
    10. }
    11. printf("存在这个文件!!!\n");
    12. char s[32] = "hello world!";
    13. int i = 0;
    14. while (s[i] != '\0')
    15. {
    16. fputc(s[i],fp);
    17. fputc(s[i],stdout);
    18. i++;
    19. }
    20. fputc('\n',stdout);
    21. fclose(fp);
    22. return 0;
    23. }

        3.fputc
        int fputc(int c, FILE *stream);
        功能:
            向流中写入一个字符
        参数:
            c:要写入的字符
            stream:文件流指针
        返回值:
            成功返回 写入的字符ASCII码值
            失败返回 EOF

        练习:利用fputc实现在file.txt文件中写入hello world 

    1. #include <stdio.h>
    2. int main(void)
    3. {
    4. FILE *fp = NULL;
    5. fp = fopen("1.txt","r+");
    6. if (fp == NULL)
    7. {
    8. printf("没有这个文件!!!\n");
    9. return 0;
    10. }
    11. printf("存在这个文件!!!\n");
    12. char s[32] = "hello world!";
    13. int i = 0;
    14. while (s[i] != '\0')
    15. {
    16. fputc(s[i],fp);
    17. fputc(s[i],stdout);
    18. i++;
    19. }
    20. fputc('\n',stdout);
    21. fclose(fp);
    22. return 0;
    23. }

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


     
        操作系统在运行一个程序时,会默认打开三个流:
            stdin        FILE*        标准输入流   ---->键盘
            stdout         FILE*        标准输出流   ---->屏幕
            stderr         FILE*        标准出错流   ---->屏幕
        
        gets scanf getchar ->  stdin 
        puts printf putchar -> stdout 
        perror -> stderr 
       

     
     
            
    练习:  
        1.从终端输入数据并输出(fgetc、fputc)

    1. #include <stdio.h>
    2. int main(int argc, const char *argv[])
    3. {
    4. if (argc < 2)
    5. {
    6. printf("恁弄啥嘞,加文件名( ⊙ o ⊙ )啊!\n");
    7. return 0;
    8. }
    9. FILE *fp = fopen(argv[1],"r");
    10. if (fp == NULL)
    11. {
    12. printf("没有这个文件!!!\n");
    13. return -1;
    14. }
    15. printf("存在这个文件!!!\n");
    16. int ret = 0;
    17. while (ret != -1)
    18. {
    19. ret = fgetc(fp);
    20. if (ret == -1)
    21. {
    22. break;
    23. }
    24. fputc(ret,stdout);
    25. }
    26. fclose(fp);
    27. return 0;
    28. }


        
        2.用fgetc 从键盘获取数据   --- fgetc(stdin);
        将获取到的数据 写入到一个文件中。---fputc(ch,fp);
        
        如果输入q 表示输入结束!
        stdin --获取数据 --- fgetc  
        fp    --保存数据 --- fputc(ch,fp); // fp --- fopen     
     
        
                
        等价:
        ch = getchar();
        ch = fgetc(stdin);
        
        等价:
        putchar(ch);
        fputc(ch, stdout);

    1. #include <stdio.h>
    2. int main(int argc, const char *argv[])
    3. {
    4. while (1)
    5. {
    6. fputc(fgetc(stdin), stderr);
    7. }
    8. //int ret = fgetc(stdin); ====> int ret = getchar();
    9. //fputc(ret, stdout); ====>putchar(ret);
    10. return 0;
    11. }

    练习2: 
        cp  src.txt dest.txt 

    1. #include <stdio.h>
    2. int main(int argc, const char *argv[])
    3. {
    4. if (argc < 3)
    5. {
    6. printf("Usage: ./a.out \n");
    7. return 0;
    8. }
    9. FILE *srcfp = fopen(argv[1], "r");
    10. FILE *dstfp = fopen(argv[2], "w");
    11. if (NULL == srcfp || NULL == dstfp)
    12. {
    13. printf("fail fopen\n");
    14. return -1;
    15. }
    16. while (1)
    17. {
    18. int ret = fgetc(srcfp);
    19. if (EOF == ret)
    20. {
    21. break;
    22. }
    23. fputc(ret, dstfp);
    24. }
    25. fclose(srcfp);
    26. fclose(dstfp);
    27. return 0;
    28. }


        

    //面试题:    
    fgetc()/fputc()面试题:
    如何用最短的代码实现用户任意输入并打印输出。
    要求用fgetc/fputc函数实现。

    while(1) 
        fputc(fgetc(stdin),stdout);

    while(fputc(fgetc(stdin),stdout)) 
        ;


    //注意点:
    fgetc()函数的结束判断。
    1、EOF 宏来判断 ===》系统预制的文件结束标记
    end of file  -1

    5.fputs
        int fputs(const char *s, FILE *stream);
        功能:
               向流中写入一行字符串       
        参数: s 
                   要写的信息,一般是固定的字符串或者有数据的数组。
               stream 
                   要写入的目标文件流对象

        返回值:成功 nonnegative number on success
                失败 -1;
            
        注:
            不写入 '\0' 

    1. #include
    2. int main(int argc, const char *argv[])
    3. {
    4. FILE *fp = fopen("1.txt", "w");
    5. if (NULL == fp)
    6. {
    7. printf("fail fopen\n");
    8. return -1;
    9. }
    10. char str[] = {"hello world"};
    11. char *p = "hello world";
    12. int ret = fputs("hello world", fp);
    13. if (ret < 0)
    14. {
    15. printf("fail fputs\n");
    16. }
    17. fputs(str, fp);
    18. fputs(p, fp);
    19. fclose(fp);
    20. return 0;
    21. }


        
        puts和fputs的区别:
            1.fputs不会自动增减\n
            2.puts 会多打印\n字符

        6.fgets
        //按行读写   按字符串读写 
        fgets  -- char ---> string 
        fputs  -- char ---> string

        char *fgets(char *s, int size, FILE *stream);
        功能:
              从stream流对象关联的文件中获取size大小字节的文本数据
          并存储到s对应的本地内存(栈区数组,堆区内存)
              
        参数: s    要存储数据的本地内存(栈,堆)
        
               size 要获取的数据长度,单位字节。
               stream 要获取的目标文件流对象,

                可以是stdin ,程序会阻塞等待
                如果是普通文件fp 则指向文件第一行数据
        返回值:成功 返回指向有效数据的首地址,一般等于s的地址
                失败 或者 文件末尾 NULL;

    1. #include <stdio.h>
    2. int main(int argc, const char *argv[])
    3. {
    4. FILE *fp = fopen("1.txt", "r");
    5. if (NULL == fp)
    6. {
    7. printf("fail fopen\n");
    8. return -1;
    9. }
    10. char str[32] = {0};
    11. while (1)
    12. {
    13. char *p = fgets(str, 32, fp);
    14. if (NULL == p)
    15. {
    16. break;
    17. }
    18. printf("str = %s\n", str);
    19. }
    20. fclose(fp);
    21. return 0;
    22. }

            注意:
            1.fgets能读取一行就读取一行
            2.fgets会读到n个数据,如果n个数据中存在\n字符则立即停止当
              前的读取操作,如果没有\n,则读取n-1个字符,最后一个存储\0    
            3.fgets每行读取的数据后面都有一个\n,在\n后面存放一个\0
                         12345
                buf[] = '1''2''3''4''5''\n''0'

            4.gets是危险的,因为没有规范读到数据的上限              
            5.gets会去掉从终端读入的\n字符 //也读走了\n 但是将 \n 去掉了 \n --> '\0'

    作业

    1. 使用fgets\fputs实现文件的拷贝 ./a.out src dst 要求:测试两种普通文件类型

    1. #include <stdio.h>
    2. int main(int argc, const char *argv[])
    3. {
    4. if (argc < 3)
    5. {
    6. printf("error\n");
    7. return 0;
    8. }
    9. FILE *fp1 = fopen(argv[1],"r");
    10. FILE *fp2 = fopen(argv[2],"w");
    11. if (NULL == fp1 || NULL == fp2)
    12. {
    13. printf("error\n");
    14. return -1;
    15. }
    16. char s[10000];
    17. while (1)
    18. {
    19. char *p = fgets(s,1024,fp1);
    20. if (NULL == p)
    21. {
    22. break;
    23. }
    24. int ret = fputs(p,fp2);
    25. if (ret < 0)
    26. {
    27. printf("fail fputs\n");
    28. }
    29. }
    30. fclose(fp1);
    31. fclose(fp2);
    32. return 0;
    33. }

    2. 统计一个文本文件中,各种字符出现的次数

    1. #include <stdio.h>
    2. int main(int argc, const char *argv[])
    3. {
    4. if (argc < 2)
    5. {
    6. printf("error\n");
    7. return 0;
    8. }
    9. int cnt[128] = {0};
    10. int ret = 0;
    11. FILE *fp = fopen(argv[1],"r");
    12. while (1)
    13. {
    14. ret = fgetc(fp);
    15. cnt[ret]++;
    16. if (EOF == ret)
    17. {
    18. break;
    19. }
    20. }
    21. for (ret = 0; ret < 128; ret++)
    22. {
    23. printf("cnt[%d] = %-3d ",ret,cnt[ret]);
    24. if (ret % 10 == 0)
    25. {
    26. printf("\n");
    27. }
    28. }
    29. printf("\n");
    30. return 0;
    31. }


         

  • 相关阅读:
    计算机网络 实验五 RIP与OSPF实验(网络层算法)
    springboot集成canal实现同步双写
    LocalDateTime获取时间类(当前时间)
    10道高频webpack面试题快问快答
    基于华为云IOT平台实现多节点温度采集(STM32+NBIOT)
    探索工业AI智能摄像机的高端科技
    一起来庆祝属于GISer的节日GIS DAY!
    Vite和Webpack的区别是什么,你站队谁?
    草履虫都能上手用的人工智能模型
    【JS函数】JS函数之高阶函数、组合函数、函数柯里化
  • 原文地址:https://blog.csdn.net/m0_75240018/article/details/136218966