zoukankan      html  css  js  c++  java
  • C语言常见文件操作

    在C语言中主要通过标准的I/O函数来对文本文件进行操作。常见的文本操作函数包括
    fopen()(打开) fclose()(关闭) fgetc()(读取字符) fputs()(写入字符) fprintf()(写入) fscanf()(读取)

    1.打开文件

    函数原型:

    FILE * fopen(const char * path,const char * mode);

    其中:
    path :文件完整路径(如果没有指定路径,则默认为当前工作目录)
    mode :为指定的打开模式

    如果打开成功,fopen会返回一个结构指针地址,否则返回一个NULL。

    FILE *fp;
    fp = fopen("c:\temp\test.txt", "r")

    使用fopen()函数打开的文件会先将文件复制到缓冲区。注意:所下达的读取或写入动作,都是针对缓冲区进行存取而不是磁盘,只有当使用fclose()函数关闭文件时,缓冲区中的数据才会写入磁盘。

    1.1打开模式:

    “r”:只能从文件中读数据,该文件必须先存在,否则打开失败
    “w”:只能向文件写数据,若指定的文件不存在则创建它,如果存在则先删除它再重建一个新文件
    “a”:向文件增加新数据(不删除原有数据),若文件不存在则会建立该文件
    “r+”:可读/写数据,该文件必须先存在,否则打开失败
    “w+”:可读/写数据,用该模式打开新建一个文件,先向该文件写数据,然后可读取该文件中的数据
    “a+”:可读/写数据,原来的文件不被删去,位置指针移到文件末尾

    打开二进制文件的模式与打开文本文件的含义是一样的,不同的是模式名称里面多一个字母’b’,以表示以二进制形式打开文件。

    2.关闭文件:

    函数原型:

    int fclose( FILE *fp );

    返回值:如果流成功关闭,fclose 返回 0,否则返回EOF(-1)。(如果流为NULL,而且程序可以继续执行,fclose设定error number给EINVAL,并返回EOF。)

    注:在执行完文件的操作后,要进行“关闭文件”操作。虽然程序在结束前会自动关闭所有的打开文件,但文件打开过多会导致系统运行缓慢,这时就要自行手动关闭不再使用的文件,来提高系统整体的执行效率。

    FILE *fp;
    fp = fopen("c:\temp\test.txt", "r");
    
    if(fp == NULL)
        printf("fail to open the file! 
    ");
    else
    {
        printf("The file is open! 
    ");
        fclose(fp);
    }

    3.字符存取函数

    函数原型为:

    int fputc (char c, File *fp)
    int fgetc(FILE *stream);

    字符读取函数fgetc()可从文件数据流中一次读取一个字符,然后读取光标移动到下一个字符,并逐步将文件的内容读出。

    如果字符读取成功,则返回所读取的字符,否则返回EOF(end of file)。EOF是表示数据结尾的常量,真值为-1。另外,要判断文件是否读取完毕,可利用feof()进行检查。未完返回0,已完返回非零值。

    feof()函数原型为:

    int feof(FILE *stream);
    #include <stdio.h>
    
    main()
    {
        FILE *fp;
        fp = fopen("c:\temp\test.txt", "r");
        if(fp != NULL)
        {
            while(!feof(fp))
                printf("%c", fgetc(fp));
        }
        else
            printf("fail to open! 
    ");
        fclose(fp);
    
        return 0;
    }

    若要将字符逐一写入文件,用fputc()函数。

    示例为:

    #include <stdio.h>
    #include <conio.h>
    
    main()
    {
        char filename[20], ch;
        FILE *fp;
        printf("Enter a filename: ");
        scanf("%s", filename);
        printf("Enter some characters to output to file: ");
        if((fp = fopen(filename, "w")) == NULL)
            printf("fail to open! 
    ");
        else
        {
            while((ch = getche()) != '15')
                fputc(ch, fp);
        }
        fclose(fp);
    
        return 0;
    }

    4.字符串存取函数

    函数原型为:

     int  fputs(const char *, FILE *);
    char *  fgets(char *, int, FILE *);

    fgets函数的作用是从指定文件读入一个字符串,如:fgets(str, n, fp);

    参数n为要求得到的字符个数,但只从fp指向的文件输入n-1个字符,然后在最后加一个’’字符,因此得到的字符串共有n个字符,把它们放在字符数组str中。如果在读完n-1个字符之前遇到换行符或EOF,读入结束。

    fputs函数的作用是向指定文件输出一个字符串,如:fputs(“Hey”, fp);

    把字符串”Hey”输出到fp指向的文件。fputs函数的第一个参数可以是字符串常量、字符数组名或字符型指针。若输出成功,则返回0,否则返回EOF。
    2.5 格式化存取函数
    函数原型为:

     int  fprintf(FILE *, const char *, ...);
     int  fscanf(FILE *, const char *, ...);

    它们与printf和scanf函数相仿,都是格式化读写函数。不同的是:fprintf和fscanf函数的读写对象不是终端(标准输入输出),而是磁盘文件。printf函数是将内容输出到终端(屏幕),因此,fprintf就是将内容输出到磁盘文件了。

    #include <stdio.h>
    
    void main()
    {
        FILE *fp;
    
        int num = 10;
        char name[10] = "Leeming";
        char gender = 'M';
    
        if((fp = fopen("info.txt", "w+")) == NULL)
            printf("can't open the file! 
    ");
        else
            fprintf(fp, "%d, %s, %c", num, name, gender); //将数据格式化输出到文件info.txt中
    
        fscanf(fp, "%d, %s, %c", &num, name, &gender); //从文件info.txt中格式化读取数据
        printf("%d, %s, %c 
    ", num, name, gender); //格式化输出到屏幕
    
        fclose(fp);
    }

    5. 指针重返函数

    函数原型为:

     void  rewind(FILE *);

    rewind函数的作用是使位置指针重返回文件的开头,属于文件的定位。

    6.二进制文件操作

    6.1 数据块存取函数

    函数原型:

     size_t  fread(void *, size_t, size_t, FILE *);
     size_t  fwrite(const void *, size_t, size_t, FILE *);

    当要求一次存取一组数据(如,一个数组、一个结构体变量的值),fread和fwrite函数可以解决该类问题。它们的调用形式一般为:

    fread(buffer, size, count, fp);
    fwrite(buffer, size, count, fp);

    buffer:对于fread来说,指的是读入数据的存放地址;对于fwrite来说,是要输出数据的地址。
    size:读写数据时,每笔数据的大小
    count:读写数据的笔数
    fp:文件指针

    #include <stdio.h>
    #define SIZE 3
    
    typedef enum { MM, GG } Gender;
    
    typedef struct
    {
        char name[10];
        int  age;
        Gender gender;
    } Person;
    
    void write2file(Person emp[SIZE])
    {
        FILE *fp;
        if((fp = fopen("emp.txt", "wb")) == NULL)
        {
            printf("cannot open file! 
    ");
            return;
        }
    
        for(int i=0; i<SIZE; i++)
            if(fwrite(&emp[i], sizeof(Person), 1, fp) != 1)
                printf("file write error! 
    ");
        fclose(fp);
    }
    
    void read_from_file(FILE *fp)
    {
        Person emp_out[SIZE];
    
        if((fp = fopen("emp.txt", "rb")) == NULL)
        {
            printf("cannot open file! 
    ");
            return;
        }
    
        printf("
    %d employee's information read: 
    ", SIZE);
    
        for(int i=0; i<SIZE; i++)
        {
            if(fread(&emp_out[i], sizeof(Person), 1, fp) != 1)
                if(feof(fp))
                {
                    fclose(fp);
                    return;
                }
                printf("%-5s %4d %5d 
    ", emp_out[i].name, emp_out[i].age, emp_out[i].gender);
        }
        fclose(fp);
    }
    
    void main()
    {
        FILE *fp = NULL;
        Person employee[SIZE];
    
        printf("Enter %d employee's information: 
    ", SIZE);
        for(int i=0; i<SIZE; i++)
            scanf("%s %d %d", employee[i].name, &employee[i].age, &employee[i].gender);
    
        write2file(employee);
    
        read_from_file(fp);
    }

    7. 随机存取函数fseek()

    函数原型:

     int  fseek(FILE *, long, int);

    对流式文件可以进行顺序读写,也可以进行随机读写。关键在于控制文件的位置指针,如果位置指针是按字节位置顺序移动的,就是顺序读写。如果能将位置指针按需要移动到任意位置,就可以实现随机读写。所谓随机读写,是指读完上一个字符(字节)后,并不一定要读写其后续的字符(字节),而可以读写文件中任意位置上所需要的字符(字节)。该函数的调用形式为:

    fseek(fp, offset, start);

    start:起始点。用0、1、2代替。0代表文件开始,名字为SEEK_SET,1代表当前位置,名字为SEEK_CUR,2代表文件末尾,名字为SEEK_END。

    fseek()函数一般用于二进制文件,因为文本文件要发生字符转换,计算位置时往往会发生混乱。

    调用实例如:

    fseek(fp, i*sizeof(Person), 0);
  • 相关阅读:
    程序员常去的14个顶级开发社区
    为何技术领域中女程序员较少?
    为何技术领域中女程序员较少?
    为何技术领域中女程序员较少?
    关于HTTP和HTTPS的区别
    关于HTTP和HTTPS的区别
    关于HTTP和HTTPS的区别
    Coupled model
    java和javascript日期详解
    Java 线程总结(十四)
  • 原文地址:https://www.cnblogs.com/leishitou/p/5436194.html
Copyright © 2011-2022 走看看