0%

文件操作

文章时效性提示

本文发布于 503 天前,部分信息可能已经改变,请注意甄别。

文件类型

数据文件分为文本文件和二进制文件。
数据在内存中以二进制的形式存储,如果不加以转换的输出到外存,就是二进制文件。
以ASCII字符的形式存储的文件就是文本文件。

1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main() {
    int a = 10000;
    FILE* pf = fopen("test.txt", "wb");//wb的意思是以二进制的形式写文件text.txt
    fwrite(&a, 4, 1, pf);
    fclose(pf);
    pf = NULL;
    return 0;
}

文件指针

一般通过FILE的指针来维护这个FILE结构的变量。
文件指针变量:FILE* pf

文件打开关闭

文件在读写之前先打开文件,在使用结束之后关闭文件。
在编写程序时,在打开文件的同时,会返回一个FILE*类型的指针变量指向该文件。
fopen打开文件,用fclose关闭文件。
FILE* fopen (const char *filename, const char* mode);
int fclose (FILE* stream);

文件打开方式:

文件使用方式含义如果指定文件不存在
“r”(只读)为了输入文件,打开一个已经存在的文本文件出错
“w”(只写)为了输出数据,打开一个文本文件建立新文件
“a”(追加)向文本末尾添加数据出错
“rb”(只读)为了输入数据,打开一个二进制文件出错
“wb”(只写)为了输出数据,打开一个二进制文件建立新文件
“ab”(追加)向一个二进制文件尾添加数据出错
“r+”(读写)为了读和写,打开一个文本文件出错
“w+”(读写)为了读和写,建立一个新文件建立新文件
“a+”(读写)打开一个文件,在文件尾读写建立新文件
“rb+”(读写)为了读和写,打开一个二进制文件出错
“wb+”(读写)为了读和写,新建一个二进制文件建立新文件
“ab+”(读写)打开一个二进制文件,在文件尾进行读写建立新文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
    //打开文件text.txt
    FILE* pf = fopen("test.txt", "w");
    if (pf == NULL)//打开失败
    {
        printf("%s\n",strerror(errno));
        return 0;
    }
    //打开成功
    //读文件
    //关闭文件
    fclose(pf);
    pf = NULL;
    return 0;
}

文件的顺序读写

功能函数名适用于
字符输入函数fgetc所有输入流
字符输出函数fputc所有输出流
文本行输入函数fgets所有输入流
文本行输出函数fputs所有输出流
格式化输入函数fscanf所有输入流
格式化输出函数fprintf所有输出流
二进制输入fread文件
二进制输出fwrite文件

fputc

字符输出。
int fputc ( int character, FILE * stream );

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
    FILE* pfWrite = fopen("test.txt", "w");
    if (pfWrite == NULL) {
        printf("%s\n",strerror(errno));
        return 0;
    }
    //写文件
    fputc('H', pfWrite);
    fputc('e', pfWrite);
    fputc('l', pfWrite);
    fputc('l', pfWrite);
    fputc('o', pfWrite);
    //关闭文件
    fclose(pfWrite);
    pfWrite = NULL;
    return 0;
}

程序运行后,test.txt内容改为Hello。先前的内容被抹去。
fputc一次会写入一个字符。

fgetc

字符输入。
int fgetc ( FILE * stream );

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
    FILE* pfRead = fopen("test.txt", "r");
    if (pfRead == NULL) {
        printf("%s\n",strerror(errno));
        return 0;
    }
    //读文件
    printf("%c",fgetc(pfRead));//H
    printf("%c",fgetc(pfRead));//e
    printf("%c",fgetc(pfRead));//l
    printf("%c",fgetc(pfRead));//l
    printf("%c",fgetc(pfRead));//0
    //关闭文件
    fclose(pfRead);
    pfRead = NULL;
    return 0;
}

fgetc一次读一个字符。
test.txt的内容是:Hello

fgets

文本行输入。
char * fgets ( char * str, int num, FILE * stream );

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
    char buf[1024] = {1};
    FILE* pf = fopen("test.txt", "r");
    if (pf == NULL)
    {
        printf("%s\n",strerror(errno));
        return 0;
    }
    //读文件
    fgets(buf,1024,pf);//fgets会读取到最后的换行符,所以打印时不用加\n就会换行,加了\n就换两行
    printf("%s",buf);//Hello
    fgets(buf,1024,pf);
    printf("%s",buf);//World
    //关闭文件
    fclose(pf);
    pf = NULL;
    return 0;
}

text.txt原先的内容是:

1
2
Hello
World

一个fgets会读取一行文本至最后,fgets会读取到最后的换行符,所以打印时不用加\n就会换行,加了\n就换两行。
想要读取两行文本,就用两个fgets

fputs

文本行输出。
int fputs(const char *string,FILE *stream);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
    char buf[1024] = {0};
    FILE* pf = fopen("test.txt", "w");
    if (pf == NULL) {
        printf("%s\n",strerror(errno));
        return 0;
    }
    //写文件
    fputs("hello\n", pf);
    fputs("world", pf);
    //关闭文件
    fclose(pf);
    pf = NULL;
    return 0;
}

运行程序后,test.txt的内容为:

1
2
hello
world

使用fputs函数,想在文件中换行需要自己输入\n

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
    char buf[1024] = {0};
    fgets(buf,1024,stdin);//从标准输入流读取信息(键盘)
    fputs(buf, stdout);//输出到标准输出流(屏幕)
    return 0;
}

fscanf

格式化的输入数据。
int fscnaf(FILE *stream,const char *format[,arguments]...);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <string.h>
#include <errno.h>
struct S
{
    int n;
    float f;
    char arr[10];
};
int main()
{
    struct S s = {0};
    FILE* pf = fopen("test.txt", "r");
    if (pf == NULL) {
        return 0;
    }
    //以格式化输入数据
    fscanf(pf, "%d %f %s",&(s.n),&(s.f),&(s.arr));
    printf("%d %f %s\n",s.n,s.f,s.arr);
    fclose(pf);
    pf = NULL;
    return 0;
}

test.txt的内容是:100 3.140000 Hello
程序运行后,屏幕上输出:100 3.140000 Hello

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <string.h>
#include <errno.h>
struct S
{
    int n;
    float f;
    char arr[10];
};
int main()
{
    struct S s ={ 0 };
    fscanf(stdin, "%d %f %s",&(s.n),&(s.f),&(s.arr));//从标准输入流获取数据(键盘)
    fprintf(stdout, "%d %f %s",s.n,s.f,s.arr);//从标准输出流输出数据(屏幕)
}

fprintf

以格式化的形式写文件。
int fprintf ( FILE * stream, const char * format, ... );

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <string.h>
#include <errno.h>
struct S
{
    int n;
    float f;
    char arr[10];
};
int main()
{
    struct S s = {100,3.14,"Hello"};
    FILE* pf = fopen("test.txt", "w");
    if (pf == NULL)
    {
        return 0;
    }
    //以格式化的形式写文件
    fprintf(pf, "%d %f %s",s.n,s.f,s.arr);
    fclose(pf);
    pf = NULL;
    return 0;
}

程序运行后,test.txt被改为:100 3.140000 Hello

fread

以二进制的形式读文件。
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <string.h>
#include <errno.h>
struct S
{
    char name[20];
    int age;
    double score;
};
int main()
{
    struct S s ={ 0 };
    FILE* pf = fopen("test.txt", "rb");
    if (pf == NULL) {
        return 0;
    }
    //二进制形式读文件
    fread(&s, sizeof(struct S), 1, pf);
    printf("%s %d %lf\n",s.name,s.age,s.score);
    fclose(pf);
    pf = NULL;
    return 0;
}

test.txt的内容为张三 12 111.999000
输出的结果是张三 12 111.999000

fwirte

以二进制的形式写文件。
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <string.h>
#include <errno.h>
struct S
{
    char name[20];
    int age;
    double score;
};
int main()
{
    struct S s = {"张三",12,111.999};
    FILE* pf = fopen("test.txt", "w");
    if (pf == NULL)
    {
        return 0;
    }
    //二进制形式写文件
    fwrite(&s, sizeof(struct S), 1, pf);
    fclose(pf);
    pf = NULL;
    return 0;
}

程序运行后,test.txt的内容被改为张三 12 111.999000

文件的随机读写

fseek

根据文件指针的位置和偏移量来定位文件指针。
int fseek (FILE* stream , long int offset , int origin );
long int offset是偏移量,int origin是文件指针的当前位置。

test.txt文件的内容是abcdef

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
    FILE* pf = fopen("test.txt", "r");
    if (pf == NULL)
    {
        return 0;
    }
    //1、定位文件指针
    fseek(pf, 1, SEEK_CUR);
    //2、读取文件
    int ch = fgetc(pf);
    printf("%c\n",ch);//b
    fclose(pf);
    pf = NULL;
}

ftell

返回文件指针相对于起始位置的偏移量。
long int ftell (FILE *stream);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
    FILE* pf = fopen("test.txt", "r");
    if (pf == NULL) {
        return 0;
    }
    fgetc(pf);
    //读取文件
    int pos = ftell(pf);
    printf("%d\n",pos);
    fclose(pf);
    pf = NULL;
}

打印的结果是1

rewind

让文件指针位置回到文件的起始位置
void rewind (FILE* stream);

test.txt文件的内容是abcdef

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
    FILE* pf = fopen("test.txt", "r");
    if (pf == NULL) {
        return 0;
    }
    int ch = fgetc(pf);//读取的结果是a
    printf("%c ",ch);
    //2、读取文件
    rewind(pf);
    ch = fgetc(pf);//还是a
    printf("%c ",ch);
    fclose(pf);
    pf = NULL;
}

文件结束的判定

被错误使用的feof

在文件读取的过程中,不能用feof的返回值判断文件是否读取结束。
这个函数是用于当文件读取结束时,判断时读取失败结束,还是遇到文件尾结束。

test.txt文件的内容是abcdef

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
    FILE* pf = fopen("test.txt", "r");
    if (pf == NULL) {
        perror("open file test.txt");
        return 0;
    }
    int ch = 0;
    while ((ch = fgetc(pf)) != EOF)
    {
        putchar(ch);
    }
    if (ferror(pf)) {
        printf("error\n");
    }
    else if (feof(pf))
    {
        printf("end of file\n");
    }
    fclose(pf);
    pf = NULL;
}

打印的结果是abcdefend of file