zoukankan      html  css  js  c++  java
  • 文件操作基础入门

    在C语言体系中,文件操作对于初学者一直是个神奇的存在,为什么呢?因为文件为什么能通过指针来操作一直是个迷。
    而且初学者第一次接触了FILE* 这个系统定义的指针类型,可容易因为陌生感而产生畏难情绪,很可惜,本文假定读者已经走过了
    对一些系统定义的畏难阶段,不算老手,但是也不完全是 菜鸟。现在,我们一起来操作文件

    常用函数一(api)

    - fopen
    - fread
    - fwrite
    - fclose
    

    基础读写

    如果你打开过window系统的 .txt文档,在里面写过情书,那么你应该完全会对此编程。
    下面,我们来编码向,poem.txt中写一段情话。一般的,你会把情书放在E盘的根目录下,当然,这里是假设,因为我是这么干的,然后就可以开始读取本情书了:

    #include<stdio.h>
    #include<stdlib.h>
    int main()
    {
    //定义文件的名称变量
    char*filename_or_path ="E:\poem.txt";
    //以写入的方式 打开文件
    FILE *file_point_write = fopen(filename_or_path,"w");
    char*poem_duc ="Do you want to date with me?";
    //写入情书内容
    int writeLenght = fwrite(poem_duc,sizeof(char),
    strlen(poem_duc),file_point_write);
    //关闭本文件
    fflush(file_point_write);
    fclose(file_point_write);
    //以读取的方式 打开本文件
    FILE *file_point_read = fopen(filename_or_path,"r");
    char buffer[100]={0x0};
    //读取到buf缓存中
    int readLenght = fread(buffer,sizeof(char),100,file_point_read);
    printf("%s
    ",buffer);
    fclose(file_point_read);
    return0;
    }

    是的,你的情书 就这么被妹子打开看到了,虽然 ,内容很直白,但是效果还是很好的。

    从上例可以看到,我们要操作某个文件,必须先使用fopen以某种方式将文件打开,这个东西叫文件打开的mode,百度一下,你就知道了。另外,在区分文本文件和2进制文件的系统中 ,在mode里加一个b是个不错的注意,但是在posix协议的linux系统下,似乎没什么作用。

    以特定的mode开后,我们就可以进行特定的操作,这个操作与mode必须对应,比如你使用r打开的文件就无法使用write功能,或者无效。

    常用函数二(api)

    #include<stdio.h>
    int fseek(FILE *stream,long offset,int whence);
    long ftell(FILE *stream);
    void rewind(FILE *stream);
    int fgetpos(FILE *stream,fpos_t*pos);
    int fsetpos(FILE *stream,constfpos_t*pos);

    文件流

    文件流 本质上是一个结构体的指针类型,FILE在头文件stdio中 定义。是的,所有的文件操作其实都是在操作这个流,这个概念到了C++中就直接使用了stream这个单词了,如果我早一点知道流这个概念,学期C++就不会那么蒙蔽了,IO操作的本质都是流概念。

    废话不多说,除了读写,我们还可以怎样操作流呢,流可以类比成水流,我们可以获取它流到的位置,以及在特定的流位置进行操作。

    当我们对文件流进行了读取或者写入操作后,文件流的指示器将发生位置改变,给个比喻,就是我作为领导 派遣一名小兵去巡视 河流,这个小兵一边巡视,其位置也是要随着河流的流向而变化的。这个小兵就是 文件流的指示器。那么如果我想要重新巡视一次,那就就得将小兵安排到河流的开始,或者我想要从某个位置开始巡视,也只是要将该小兵安排到河流对应的位置即可。

    • show me the code directly
    1. //一个类似的例子
      #include<stdio.h>
      #include<string.h>
      #include<stdlib.h>
      int main(int argc,char* argv[])
      {
      constchar* fileName ="disk.txt";
      char*toWritebuff ="this is me Stultz lee";
      FILE *fp = fopen(fileName,"w");
      if(fp == NULL)
      {
      perror("file read");
      return0;
      }
      int writeLenght = fwrite(toWritebuff,sizeof(char),strlen(toWritebuff),fp);
      fclose(fp);
      fp = fopen(fileName,"r");
      char buffer[1024]={0x0};
      int readLenght = fread(buffer,sizeof(char),1024,fp);
      printf("%s
      ",buffer);
      //使用ftell找到当前小兵的位置,它此时到了河流的尽头
      int index = ftell(fp);
      printf("%d
      ",index);//得到21
      //fseek 地点为SEEK_SET,;偏移量为0 时 与rewind意义相同,//都是要将该小兵放到河流的开头去
      //fseek(fp,0,SEEK_SET);
      rewind(fp);
      index = ftell(fp);
      //int readLenght = fread(buffer,sizeof(char),1024,fp);
      printf("%d
      ",index);//得到0
      memset(buffer,0,1024);
      readLenght = fread(buffer,sizeof(char),1024,fp);
      printf("%s
      ",buffer);
      #if 0
      fseek(fp,-1,SEEK_SET);
      index = ftell(fp);
      //int readLenght = fread(buffer,sizeof(char),1024,fp);
      printf("%d
      ",index);//得到0
      fseek(fp,1,SEEK_END);
      index = ftell(fp);
      //int readLenght = fread(buffer,sizeof(char),1024,fp);
      printf("%d
      ",index);//得到22
      fseek(fp,-1,SEEK_END);
      index = ftell(fp);
      //int readLenght = fread(buffer,sizeof(char),1024,fp);
      printf("%d
      ",index);//得到20
      #endif
      return0;
      }

    备注 int fgetpos(FILE stream, fpos_t pos);
    int fsetpos(FILE stream, const fpos_t pos);
    使用不多,fpos_t可能是一个复杂的结构体,使用fseek,ftell,足以完成大部分文件流的偏移量转换工作,我们没必要把问题搞复杂。

    以上是最简单的文件操作,适合基础入门,后面的文章,我将结合多线程的文件操作和网络编程来深入学习文件操作。记住,在linux中,一切都是文件 ,但是 我们不直接使用linux的 系统调用,比如open,write ,read等,而是使用fopen,fread,fwrite等函数,根本原因在于 系统调用会直接性的与 内核交互,这在多次的操作中 ,反而没有库函数来的效率高。

  • 相关阅读:
    TestPaste text
    WPF XML序列化保存数据 支持Datagrid 显示/编辑/添加/删除数据
    C# WPF xml序列化 反序列化
    C# show FTP Download/Upload progress
    BAT for 循环
    C# httpRequest Soap请求
    day6 os模块
    day6 random随机数模块
    day6 time和datetime模块
    day5 常用模块json和pickle
  • 原文地址:https://www.cnblogs.com/Stultz-Lee/p/6766854.html
Copyright © 2011-2022 走看看