C 文件


读写一个文件有3个步骤:

  1. 打开文件。读写文件需要一个文件指针(file pointer),使用fopen函数打开文件,得到一个文件指针。
  2. 对文件进行一或多次读写操作。
  3. 关闭文件。使用fclose函数关闭文件。

打开文件时文件的访问模式有下面几种:

  • "r": 为读取打开文件,文件必须存在。
  • "w": 为写入创建一个文件,如果文件存在,清除文件的内容。
  • "a": 添加数据到文件的结尾处,如果文件不存在,创建文件。
  • "r+": 为读取和写入打开文件,文件必须存在。
  • "w+": 为读取和写入创建一个文件,如果文件存在,清除文件的内容。
  • "a+": 为读取和添加打开文件,添加数据只能加在结尾处。可以读取文件任意位置处的数据。

上面的模式处理文本文件,"rb"、"wb"、"ab"、"rb+"、"wb+"、"ab+"用来处理二进制文件。

读写文件

getc、fgetc函数从文件中读取一个字符。如果读取成功,返回读取的字符,否则,返回EOF。

putc、fputc函数写一个字符到文件。如果写入成功,返回写入的字符,否则,返回EOF。

fgets函数从文件中读取字符串,直到读取到指定的读取长度 - 1个字符或读到换行符或EOF。字符'\0'会被自动附加到读取到的字符串的最后,标识字符串的结束。如果读取出错,返回NULL。

fputs函数写一个字符串到文件中。从写入字符串的地址处开始复制数据到文件中,直到遇到字符'\0'。'\0'不会复制到文件中。如果写入成功,返回一个非负值,否则返回EOF。

fscanf函数从文件中读取格式化数据。fprintf函数输出格式化字符串到文件。

下面是读写文件的例子:

#include <stdio.h>
int main(int argc, const char * argv[]) {
    FILE *fp;
    char str[100];
    float f;

    fp = fopen("1.txt", "w+");
    if (fp == NULL)
        perror("Failed to open file");
    else {
        fputs("hello", fp);
        rewind(fp);
        if (fgets(str, 100, fp) != NULL)
            printf("%s \n", str);   // hello

        rewind(fp);

        fprintf(fp, "%f %s", 12.34, "apple");
        rewind(fp);
        fscanf(fp, "%f", &f);
        fscanf(fp, "%s", str);

        printf("%f, %s \n", f, str);  // 12.340000, apple 

        fclose(fp);
    }

    return 0;
}

文件位置

ftell函数返回文件指针的当前位置。如果成功,返回文件位置,否则返回EOF。

fgetpos函数返回文件指针的当前位置。如果成功,返回0,否则返回非0值。

fseek、fsetpos函数设置文件指针的位置,如果成功返回0,否则返回非0值。

有3个预定义的文件位置:

  • SEEK_SET 文件的开始位置
  • SEEK_CUR 文件指针的当前位置
  • SEEK_END 文件的结尾位置

rewind函数将文件指针移到文件的开始位置。

下面是文件位置的例子:

#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[]) {
    FILE *fp;
    int c;
    fpos_t pos;

    fp = fopen("1.txt", "w+");
    if (!fp) {
        perror("Failed to open file");
        exit(EXIT_FAILURE);
    }

    fputs("hello", fp);
    fseek(fp, 1, SEEK_SET);
    if ((c = fgetc(fp)) != EOF)
        printf("%c \n", c);   // e

    printf("pos : %ld \n", ftell(fp));  // 2

    pos = 4;
    if (fsetpos(fp, &pos) != 0) {
        perror("fsetpos failed");
        exit(EXIT_FAILURE);
    }

    if ((c = fgetc(fp)) != EOF)
        printf("%c \n", c);   // o 

    fclose(fp);

    return 0;
}

读写二进制文件

fread函数从文件中读取数据块。如果成功,返回指定要读取的数据块的个数,否则可能是出错或到了文件结尾。

fwrite函数向文件上写入数据块。如果成功,返回指定要读取的数据块的个数,否则表示出错了。

下面是读写二进制文件的例子:

#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[]) {
    FILE *fp;
    double a[3] = {1, 2, 3};

    fp = fopen("1.bin", "wb+");
    if (!fp) {
        perror("Failed to open file");
        exit(EXIT_FAILURE);
    }

    fwrite(a, sizeof a[0], 3, fp);

    rewind(fp);

    double b[3];
    size_t count = fread(b, sizeof b[0], 3, fp);

    printf("count : %ld \n", count);  // 3
    printf("b[1] : %f \n", b[1]);     // 2.000000 

    fclose(fp);

    return 0;
}