c语言文件 *** 作--标准IO

c语言文件 *** 作--标准IO,第1张

目录

一、缓冲文件系统

1、目的

2、定义

3、分类

二、EOF,stdin、stdout、stderr

三、标准IO函数

1、fopen()、fclose()

 2、feof()、ferror()、clearerr()、perror()

3、getc()、getchar()、fgetc()

4、putc()、fputc()、putchar()

5、puts()、fputs()

 6、gets()、fgets()

7、fread()、fwrite()

 8、fprintf()、 fscanf()

9、fseek()、ftell()、rewind()


一、缓冲文件系统 1.1、目的

▪ 尽量减少使用read/write的调用

1.2、定义

▪ 系统自动的在内存中为每一个正在使用的文件开辟一个缓冲区, 从内存向磁盘输出数据必须先送到内存缓冲区,装满缓冲区在一起送 到磁盘中去。

▪ 从磁盘中读数据,则一次从磁盘文件将一批数据读入到 内存缓冲区中,然后再从缓冲区逐个的将数据送到程序的数据区。

1.3、分类

a、全缓存

▪ 当填满I/O缓存后才进行实际I/O *** 作,或者满足一定条件后,系统通过调用malloc来获得所需要的缓冲区域

▪ 当缓冲区满了,或者满足一定的条件后,就会执行刷新 *** 作。

b、行缓存

▪ 当在输入和输出中遇到新行符(‘\n’)时,进行I/O *** 作

c、不缓存

▪ 标准I/O库不对字符进行缓冲,例如stderr。

▪ 很多的人机交互界面要求不可全缓存。

▪  标准出错决不会是全缓存的。 

d、在任何时刻,可以使用fflush强制刷出缓存区

二、EOF,stdin、stdout、stderr

extern FILE *stdin; 标准输入
extern FILE *stdout; 标准输出
extern FILE *stderr; 标准错误

//EOF end of file 文件结束符
三、标准IO函数 3.1、fopen()、fclose()

a、函数定义

#include 

FILE *fopen(const char *pathname, const char *mode);
int fclose(FILE *stream);

b、参数含义

▪ pathname:路径
        绝对路径:"D:/test01/a.txt"
        相对路径 "./a.txt"
▪ mode:访问方式
        w write 只写 文件不存在则创建,文件存在则清空
        r read 只读 不能创建
        a apped 以追加的方式写 文件不存在则创建
        b binary 以二进制的方式 *** 作 wb rb ab
        + 可读可写 w+ r+ a+

c、 注意事项

  • fopen():成功返回文件指针,失败返回NULL
  • fclose():成功返回0,失败返回EOF
  • 在该文件被关闭之前,刷新缓存中的数据。
  • 当一个进程正常终止时,则所有带未写缓存数据的标准I / O流都被刷新,所有打开的标准I / O流都被关闭。
  • 在调用fclose()关闭流后对流所进行的任何 *** 作,包括再次调用fclose(),其 结果都将是未知的
3.2、feof()、ferror()、clearerr()、perror()

a、函数定义

#include 

void clearerr(FILE *stream);
int feof(FILE *stream);
int ferror(FILE *stream);
void perror(const char *s);

 b、注意事项

  • feof()检测文件结束符,如果文件结束,返回非0值,否则返回0(一般先读取再判断)
  • ferror()检测错误标识符,如果有返回非0值,否则返回0 (如:读取只写;返回非0值)
  • clearerr()清除文件结束符和错误标识符 且这两个只能由其清除
  • perror()在错误信息打印之前,输出自定义信息
3.3、getc()、getchar()、fgetc()

a、函数定义

#include 

int fgetc(FILE *stream);
int getc(FILE *stream);
int getchar(void);

b、 注意事项

  • 三个函数都是从流中获取一个字符、返回值为int型
  • 成功返回获取的字符,若已处于文件尾端或出错则返回EOF,要区分这两种不同的情况,必须调用ferror()或feof()。
  • getc()等价于fgetc(),只是getc()的实现是一个宏,而fgetc()是一个函数。
  • 函数getchar()等同于getc(stdin)
3.4、putc()、fputc()、putchar()

a、函数定义

#include 

int fputc(int c, FILE *stream);
int putc(int c, FILE *stream);
int putchar(int c);

b 、注意事项

  • 成功返回写入的字符,失败返回EOF
  • putc()等价于fputc(),只是putc()的实现是一个宏,而fputc()是一个函数。
  • putchar('c')等价于putc('c',stdout)。
3.5、puts()、fputs()

a、函数定义

#include 

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

b、注意事项

  • 成功返回非负数(不是写入的字符数),失败返回EOF
  • 两个都是遇到  不会主动 就停止写入,不会将 会主动 写入 , 遇到 \n 不会停止写入
  • fputs
  • 成功返回缓存的首地址(即 s),若已处文件尾端或出错则为null
  • 添加\n符号到目标流内()
  • puts
  • fgets最多读取size-1个字符 并在后面加上
  • 不推荐使用 gets(),因为gets()不能指定缓存的长度,这样就可能造成缓存越界;
  • ,当遇到 \n 会结束读取,并将 \n 写入,\n算两个字符添加\n符号到标准输出中
3.6、gets()、fgets()

a、函数定义

 #include 

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

b、注意事项

  • ptr:要读/写内容的首地址
  • size:一般为ptr所指向类型的大小 
  •      size和nmemb不固定,只要 size*nmemb = sizeof(a) 就行
3.7、fread()、fwrite()

a、函数定义

#include 

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);

b、参数含义

  • nmemb:要读/写的条目数
  • stream:要读/写的文件

                假如: char a[10];  char *ptr = a; 则size = sizeof(char)

           

  • 成功返回读/写入的 nmemb 的值(不一定为nmemb),错误或到达文件末尾返回0
    • 可以以二进制的方式读/写
    • 成功返回写入的字节数,失败返回 EOF

    c、注意事项

    • prinf() == fprintf(stdout,)
    • scanf() == fscanf(stdin,)
    3.8、fprintf()、 fscanf()

    a、函数定义

    #include 
    
    int fprintf(FILE *stream, const char *format, ...);
    int fscanf(FILE *stream, const char *format, ...);

    b、注意

    • fseek
    • ftell
    • rewind
    3.9、fseek()、ftell()、rewind()

    a、函数定义

    #include 
    
    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, const fpos_t *pos);
      int FileCopy(const char *src_path,const char*dest_path){ //获取源文件的文件指针 FILE *src_fd = fopen(src_path,"r"); if(src_fd == NULL){ perror("open src "); return -1; } //获取目标文件的文件指针 FILE *dest_fd = fopen(dest_path,"w"); if(dest_fd == NULL){ perror("open dest "); return -1; } /*利用标准IO的字符IO,实现2个文件拷贝*/ // fputc(fgetc(src_fd),dest_fd); // while (!feof(src_fd)){ // fputc(fgetc(src_fd),dest_fd); // } /*利用标准IO的行IO,实现2个文件拷贝*/ // char buf[1024]; // while( fgets(buf, sizeof(buf),src_fd) != NULL){ // fputs(buf,dest_fd); // } /*利用标准IO的块IO,实现2个文件拷贝*/ char buf[1024]; unsigned long ret = 0; ret = fread(buf, 1,sizeof(buf),src_fd); while( ret != 0){ fwrite(buf, 1,ret,dest_fd); //读到多少就写入多少 printf("%ld\n",ret); ret = fread(buf, 1,sizeof(buf),src_fd); } fclose(src_fd); fclose(dest_fd); return 0; }

    用于重置stream流的位置,调用成功返回0,失败返回 -1

    offset:偏移量,每一读写 *** 作所需要移动的距离,单位是字节的 ,可正可负(向前移,向后移)

    whence :
    SEEK_SET:当前位置为文件的开头,新位置为偏移量 的大小。
    SEEK_CUR:当前位置为文件指针的位置,新位置为 当前位置加上偏移量。
    SEEK_END:当前位置为文件的结尾,新位置为文件的大小加上偏移量的大小。

      long SizeOfFile(const char *path){ long size = 0L; FILE *fd = fopen(path,"r"); fseek(fd,0,SEEK_END);//偏移到文件末尾 size = ftell(fd); fclose(fd); return size; }

     用于获取当前文件位置,调用成功返回当前偏移量。失败返回  -1

      将stream 流设置在文件开头 无返回值

       相当于  fseek(stream, 0L, SEEK_SET)

      四、一些简单实践 4.1、文本文件的拷贝
       
      4.2、打印日志文件 
      

      编程读写一个文件 test.txt,每隔 1 秒向文件中写入一行数据,类似这样

      0001, 2022-05-08 15:16:42

      0002, 2022-05-08 15:16:43

      该程序应该无限循环,直到中断程序。下次再启动程序写文件时可以追加到原 文件之后,并且序号能够接续上次的序号,比如:

      0001,2022-05-08 15:16:42

      0002, 2022-05-08 15:16:43

      0003, 2022-05-08 15:19:02

      0004, 2022-05-08 15:19:03

      0005, 2022-05-0815:19:04

      void PrintLogData(const char *path){
          //追加的方式获取文件描述符
          FILE *fd = fopen(path,"a+");
          if(fd == NULL){
              perror("open ");
              return;
          }
      
          //获取行号
          int num = 0;
          char buf[1024];
          while(fgets(buf, sizeof(buf),fd) !=NULL){
              num++;
          }
          //重置一下fd
          fseek(fd,0,SEEK_CUR);
      
          //往日志文件写数据
          int year,mon,day,hour,min,sec;
          while(num >= 0){
      
              //获取当前时间
              time_t now;
              struct tm *tm_now;
              time(&now);
              tm_now = localtime(&now);
      
              year = tm_now->tm_year+1900;
              mon = tm_now->tm_mon+1;
              day = tm_now->tm_mday;
              hour = tm_now->tm_hour;
              min = tm_now->tm_min;
              sec = tm_now->tm_sec;
      
              //%04 表示占4位,不足4位 在前面补0
              fprintf(fd,"%04d, %02d-%02d-%02d %02d:%02d:%02d\n"
                      ,num,year, mon,day,hour,min,sec);
              fflush(fd);//强制刷出缓存
      
              //在控制台实时打印
              fprintf(stdout,"%04d, %02d-%02d-%02d %02d:%02d:%02d\n"
                      ,num,year, mon,day,hour,min,sec);
              sleep(1);
              num++;
          }
      
          fclose(fd);
      }
       4.3、查看文件的大小
       
      4.4、完整测试代码 
      
      #include 
      #include 
      #include 
      
      //文本文件拷贝
      int FileCopy(const char *src_path,const char*dest_path);
      //输出日志文件
      void PrintLogData(const char *path);
      //获取文件大小
      long SizeOfFile(const char *path);
      
      int main() {
          char* src_path="./src.txt";
          char* dest_path="./dest.txt";
          char* log_path = "log.txt";
      //    PrintLogData(log_path);
      //    FileCopy(src_path,dest_path);
      //    printf("%ld\n", SizeOfFile(src_path));
          return 0;
      }
      
      int FileCopy(const char *src_path,const char*dest_path){
          //获取源文件的文件指针
          FILE *src_fd = fopen(src_path,"r");
          if(src_fd == NULL){
              perror("open src ");
              return -1;
          }
          //获取目标文件的文件指针
          FILE *dest_fd = fopen(dest_path,"w");
          if(dest_fd == NULL){
              perror("open dest ");
              return -1;
          }
      
          /*利用标准IO的字符IO,实现2个文件的字节拷贝*/
      //    fputc(fgetc(src_fd),dest_fd);
      //    while (!feof(src_fd)){
      //        fputc(fgetc(src_fd),dest_fd);
      //    }
      
          /*利用标准IO的行IO,实现2个文件的字节拷贝*/
      //    char buf[1024];
      //    while( fgets(buf, sizeof(buf),src_fd) != NULL){
      //        fputs(buf,dest_fd);
      //    }
      
          /*利用标准IO的块IO,实现2个文件的字节拷贝*/
          char buf[1024];
          unsigned long ret = 0;
          ret = fread(buf, 1,sizeof(buf),src_fd);
          while( ret != 0){
              fwrite(buf, 1,ret,dest_fd); //读到多少就写入多少
              printf("%ld\n",ret);
              ret = fread(buf, 1,sizeof(buf),src_fd);
          }
      
          fclose(src_fd);
          fclose(dest_fd);
          return 0;
      }
      
      void PrintLogData(const char *path){
          //追加的方式获取文件描述符
          FILE *fd = fopen(path,"a+");
          if(fd == NULL){
              perror("open ");
              return;
          }
      
          //获取行号
          int num = 0;
          char buf[1024];
          while(fgets(buf, sizeof(buf),fd) !=NULL){
              num++;
          }
          fseek(fd,0,SEEK_CUR);
      
          //往日志文件写数据
          int year,mon,day,hour,min,sec;
          while(num >= 0){
      
              //获取当前时间
              time_t now;
              struct tm *tm_now;
              time(&now);
              tm_now = localtime(&now);
      
              year = tm_now->tm_year+1900;
              mon = tm_now->tm_mon+1;
              day = tm_now->tm_mday;
              hour = tm_now->tm_hour;
              min = tm_now->tm_min;
              sec = tm_now->tm_sec;
      
              //%04 表示占4位,不足4位 在前面补0
              fprintf(fd,"%04d, %02d-%02d-%02d %02d:%02d:%02d\n"
                      ,num,year, mon,day,hour,min,sec);
              fflush(fd);//强制刷出缓存
      
              fprintf(stdout,"%04d, %02d-%02d-%02d %02d:%02d:%02d\n"
                      ,num,year, mon,day,hour,min,sec);
              sleep(1);
              num++;
          }
      
          fclose(fd);
      }
      
      long SizeOfFile(const char *path){
          long size = 0L;
      
          FILE *fd = fopen(path,"r");
          fseek(fd,0,SEEK_END);//偏移到文件末尾
          size = ftell(fd);
          fclose(fd);
      
          return size;
      }

      欢迎分享,转载请注明来源:内存溢出

      原文地址:https://54852.com/langs/875741.html

      (0)
      打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
      上一篇 2022-05-13
      下一篇2022-05-13

      发表评论

      登录后才能评论

      评论列表(0条)

        保存