文件操作基础入门

在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\n",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\n",buffer);
    //使用ftell找到当前小兵的位置,它此时到了河流的尽头
    int index = ftell(fp);
    printf("%d\n",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\n",index);//得到0
    memset(buffer,0,1024);
    readLenght = fread(buffer,sizeof(char),1024,fp);
    printf("%s\n",buffer);
    #if 0
    fseek(fp,-1,SEEK_SET);
    index = ftell(fp);
    //int readLenght = fread(buffer,sizeof(char),1024,fp);
    printf("%d\n",index);//得到0
    fseek(fp,1,SEEK_END);
    index = ftell(fp);
    //int readLenght = fread(buffer,sizeof(char),1024,fp);
    printf("%d\n",index);//得到22
    fseek(fp,-1,SEEK_END);
    index = ftell(fp);
    //int readLenght = fread(buffer,sizeof(char),1024,fp);
    printf("%d\n",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等函数,根本原因在于 系统调用会直接性的与 内核交互,这在多次的操作中 ,反而没有库函数来的效率高。

posted @ 2017-04-26 08:48  Lckfa  阅读(436)  评论(0编辑  收藏  举报