0%

C语言文件操作

fwrite()和fread()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) 
把 ptr 所指向的数组中的数据写入到给定流 stream 中。
size -- 这是要被写入的每个元素的大小,以字节为单位。
nmemb -- 这是元素的个数,每个元素的大小为 size 字节。
如果成功,该函数返回一个 size_t 对象,表示元素的总数,该对象是一个整型数据类型。

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
从给定流 stream 读取数据到 ptr 所指向的数组中。
size -- 这是要读取的每个元素的大小,以字节为单位。
nmemb -- 这是元素的个数,每个元素的大小为 size 字节
成功读取的元素总数会以 size_t 对象返回,size_t 对象是一个整型数据类型。如果总数与 nmemb 参数不同,则可能发生了一个错误或者到达了文件末尾。

char c[] = "This is runoob";
char buffer[20];
fwrite(c, strlen(c) + 1, 1, fp);
fseek(fp, 0, SEEK_SET);
fread(buffer, strlen(c) + 1, 1, fp);
printf("%s\n", buffer);

fprintf() fscanf() rewind()

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
int fprintf(FILE *stream, const char *format, ...) 
发送格式化输出到流 stream 中。
fprintf(fp, "%s %s %s %d", "We", "are", "in", 2021);

int fscanf(FILE *stream, const char *format, ...)
从流 stream 读取格式化输入。
fputs("We are in 2014", fp);
rewind(fp);
fscanf(fp, "%s %s %s %d", str1, str2, str3, &year);

void rewind(FILE *stream)
设置文件位置为给定流 stream 的文件的开头。


fwrite()fread()对应;
fwrite()写入txt,打开txt是乱码,但是能fread()读取;

fprintf()和fscanf()对应
fprintf()写入txt,打开能正确显示,但是不能用fread()读取。用fscanf()读取,fscanf()返回读取的个数。


写入到文件fp
fprintf(fp, "This is a test");

char s[10];
scanf("%s", s);
fprintf(fp, s);


写入与读取
while (gets(words) != NULL && words[0] != '\0')
fprintf(fp, "%s ", words); //写入到fp

rewind(fp);//指针指向文件开头
while (fscanf(fp, "%s", words) == 1) //从fp读取
puts(words);//输出


复制文件
int main(void)
{
FILE *fin = fopen("1.txt", "rb");
FILE *fout = fopen("2.txt", "wb");
char ch;
while (fscanf(fin, "%c", &ch) == 1)
{
printf("%c", ch);
fprintf(fout, "%c", ch);
}
return 0;
}

fseek() ftell()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int fseek(FILE *stream, long int offset, int whence)
设置流 stream 的文件位置为给定的偏移 offset,参数 offset 意味着从给定的 whence 位置查找的字节数。
stream -- 是指向 FILE 对象的指针,该 FILE 对象标识了流。
offset -- 是相对 whence 的偏移量,以字节为单位。
whence -- 是表示开始添加偏移 offset 的位置。指定为下列常量之一:
SEEK_SET 文件的开头
SEEK_CUR 文件指针的当前位置
SEEK_END 文件的末尾

long int ftell(FILE *stream)
返回给定流 stream 的当前文件位置。

计算文件字节数
fseek(stream, 0L, SEEK_END);
long length = ftell(stream);
length就是文件字节数

fputs("This is a test", fp);
fseek( fp, 7, SEEK_SET ); //fp指向从开始位置偏移的7个字节处
fputs(" C Programming Langauge", fp);
输出:This is C Programming Langauge

feof() fgetc(fp) fputc(ch, fp)

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
int feof(FILE *stream) 
测试给定流 stream 的文件结束标识符。

int fgetc(FILE *stream)
从指定的流 stream 获取下一个字符(一个无符号字符),并把位置标识符往前移动。
该函数以无符号 char 强制转换为 int 的形式返回读取的字符,如果到达文件末尾或发生读错误,则返回 EOF。

int fputc(int char, FILE *stream)
把参数 char 指定的字符(一个无符号字符)写入到指定的流 stream 中,并把位置标识符往前移动。
如果没有发生错误,则返回被写入的字符。如果发生错误,则返回 EOF,并设置错误标识符。


int main(void)
{
FILE *fp = fopen("1.txt", "r");
char ch = fgetc(fp); /*从文件中读取字符*/
while (!feof(fp))
{
if (ch >= 'a' && ch <= 'z')
ch = ch - 32;
putchar(ch);
ch = fgetc(fp);
}
return 0;
}

复制文件
int main(void)
{
FILE *fin = fopen("1.txt", "rb");
FILE *fout = fopen("2.txt", "wb");
char ch;
while (!feof(fin))
{
ch = fgetc(fin); //从fin中读取
fputc(ch, fout); //写入到fout
}
return 0;
}

getc() putc()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int getc(FILE *stream) 
从指定的流 stream 获取下一个字符(一个无符号字符),并把位置标识符往前移动。

int putc(int char, FILE *stream)
把参数 char 指定的字符(一个无符号字符)写入到指定的流 stream 中,并把位置标识符往前移动。


int main()
{
char c = getc(stdin);
putc(c, stdout);

return(0);
}

for (ch = 33; ch <= 100; ch++)
putc(ch, fp);

fgets() fputs()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
char *fgets(char *str, int n, FILE *stream) 
从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。

int fputs(const char *str, FILE *stream)
把字符串写入到指定的流 stream 中,但不包括空字符。

fgets() 只读取限定数量的字符。不同于gets(s), gets(s) 大小可能会超出s[] 数组的大小,有风险。
char str[1024];
fgets(str, sizeof(str), fp);


int main(void)
{
FILE *stream = fopen("1.txt", "w+");
char string[] = "This is a test";
char msg[20];
fwrite(string, strlen(string), 1, stream); //将string写入stream
fseek(stream, 0, SEEK_SET); //指针指向开头
fgets(msg, strlen(string) + 1, stream); //从stream读取string
printf("%s", msg);
return 0;
}

gets() puts()

1
2
3
4
5
6
char *gets(char *str) 
从标准输入 stdin 读取一行,并把它存储在 str 所指向的字符串中。当读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。

int puts(const char *str)
把一个字符串写入到标准输出 stdout,直到空字符,但不包括空字符。换行符会被追加到输出中。

sprintf() rename()

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
int sprintf(char *str, const char *format, ...) 
发送格式化输出到 str 所指向的字符串。
如果成功,则返回写入的字符总数,不包括字符串追加在字符串末尾的空字符。如果失败,则返回一个负数。

int sscanf(const char *str, const char *format, ...)
从字符串读取格式化输入。
如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF。

int rename(const char *old_filename, const char *new_filename)
把 old_filename 所指向的文件名改为 new_filename。
如果成功,则返回零。如果错误,则返回 -1,并设置 errno。

更改文件名或者后缀,先将文件夹放在程序所在的文件夹内
int main()
{
char old[10] = "gif";
char new[10] = "gif";
int n = 100;
for (int i = 1; i < n; i++)
{
char oldname[50];
char newname[50];
sprintf(oldname, "00/x (%d).%s", i, old);
sprintf(newname, "00/%d.%s", i, new);
rename(oldname, newname);
}
return 0;
}

从字符串读取格式化输入
int main()
{
int day, year;
char weekday[20], month[20], dtm[100];
strcpy(dtm, "Saturday March 25 1989");

sscanf(dtm, "%s %s %d %d", weekday, month, &day, &year);
printf("%s %d, %d = %s\n", month, day, year, weekday);
return (0);
}

freopen()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
FILE *freopen(const char *filename, const char *mode, FILE *stream) 
把一个新的文件名 filename 与给定的打开的流 stream 关联,同时关闭流中的旧文件。
如果文件成功打开,则函数返回一个指针,指向用于标识流的对象。否则,返回空指针。

在调用 freopen() 之后,它会关联标准输出 STDOUT 到文件 file.txt,无论我们在标准输出 STDOUT 中写了什么都会被写入 file.txt

int main()
{
FILE *fp = freopen("1.txt", "a+", stdout);
char s[100];

printf("该文本重定向到 stdout\n");
gets(s);
printf("%s\n", s);
printf("%s\n", s);
printf("%s\n", s);
fclose(fp);
return (0);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void WriteFile(FILE *fp)
{
char ch;
printf("请输入文件内容,以#结尾!\n");
while ((ch = getchar()) != '#')
fputc(ch, fp);
rewind(fp);//指针指向文件开头
}
void ReadFile(FILE *fp)
{
printf("读取文件内容\n");
char ch = fgetc(fp);
while (ch != EOF)
{
putchar(ch);
ch = fgetc(fp);
}
printf("\n文件读取结束");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
文件操作-去空格
int main(void)
{
FILE *fp = fopen("1.txt", "rb");
fseek(fp, 0L, SEEK_END); //go to end of file
// if SEEK_END not supported, use this instead
// last = 0;
// while (getc(fp) != EOF)
// last++;
long last = ftell(fp);
for (int count = 0; count <= last; count++)
{
fseek(fp, count, SEEK_SET); // go backward
char ch = getc(fp);
if (ch == ' ' || ch == '\t' || ch == '\r')
continue;
else
putchar(ch);
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
文件倒序输出
int main(void)
{
char file[50], ch;
FILE *fp = fopen(file, "rb");
puts("Enter the name of the file to be processed:");
gets(file);

fseek(fp, 0L, SEEK_END); //go to end of file
long last = ftell(fp);

for (long count = last - 1; count >= 0; count--)
{
fseek(fp, count, SEEK_SET); // go backward
ch = getc(fp);
// for DOS, works with UNIX
if (ch != '\r')
putchar(ch);
}
fclose(fp);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
文件加入字符'a'
int main()
{
FILE *fp = fopen("1.txt", "r+b"); //以二进制读写方式打开文件
//2.获取文件大小(字节数)
fseek(fp, 0, SEEK_END); //指针fp指到文件结尾;
int len = ftell(fp); //获取文件大小

fseek(fp, 0, SEEK_SET); //指针fp重新指到文件头;
//3.每个一个字符插入一个加密字符
char ch = 'a';
for (int i = 0; i < len; i++)
{
fwrite(&ch, 1, 1, fp); //写入字符;元素,大小1个字节,个数1个,fp
fseek(fp, 1, SEEK_CUR); //当前指针fp向后移动1位;
}
return 0;
}
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
26
27
28
29
30
31
32
33
34
从文件中读取结构体(不含头结点的头插法)
struct info *readFromFile()
{
struct info *head = NULL;
struct info *node = NULL;
FILE *fp = fopen("test.txt", "r");

printf("读取的数目: ");
int temp = 0;
scanf("%d", &temp);

for (int i = 0; i < temp && (!feof(fp)); i++)
{
node = solo();
//fread(node, sizeof(struct info), 1, fp);
fscanf(fp, "%s%s%d%d%d", node->name, node->no, &node->date.year, &node->date.month, &node->date.day);
node->next = head;
head = node;
}
fclose(fp);
return head;
}
输出到文件
void output(struct info *head)
{
FILE *fp = fopen("test.txt", "a");
while (head != NULL)
{
fprintf(fp, "%s\t%s\t%d\t%d\t%d\n", head->name, head->no, head->date.year, head->date.month, head->date.day);
//fwrite(head, sizeof(struct info), 1, fp);
head = head->next;
}
fclose(fp);
}
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
struct address
{
char name[10];
char adr[20];
char tel[15];
} info[100];

将一组数据输出到fp所指的文件中
void save(char *name, int n)
{
FILE *fp = fopen(name, "wb");
for (int i = 0; i < n; i++)
fwrite(&info[i], sizeof(struct address), 1, fp);
fclose(fp);
}
从fp所指向的文件读入数据存到数组score中
void show(char *name, int n)
{
FILE *fp = fopen(name, "rb");
for (int i = 0; i < n; i++)
{
fread(&info[i], sizeof(struct address), 1, fp);
printf("%15s%20s%20s\n", info[i].name, info[i].adr, info[i].tel);
}
fclose(fp);
}
int main()
{
char filename[50];
printf("请输入文件路径及名称:\n");
scanf("%s", filename);
printf("请输入学生的姓名、地址、电话:\n");
for (int i = 0; i < 3; i++)
{
scanf("%s%s%s", info[i].name, info[i].adr, info[i].tel);
save(filename, n);
}
show(filename, n);
return 0;
}
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 20
#define M 3
struct stu
{
char name[N];
int score[M];
double avg;
};

void swap(struct stu *m, struct stu *n)
{
stu t = *m;
*m = *n;
*n = t;
}
void input(struct stu *s, int n)
{
double sum = 0;
for (int i = 0; i < n; i++)
{
printf("请输入姓名:");
scanf("%s", s[i].name);
printf("请输入分数(英语数C):");
for (int j = 0; j < M; j++)
scanf("%d", &s[i].score[j]);
printf("\n");
}
}
void sort(struct stu *s, int n)
{
int i, j;
for (i = 0; i < n; i++)
{
double sum = 0;
for (j = 0; j < M; j++)
sum += s[i].score[j];
s[i].avg = sum / M;
}
//排序;平均分相同则比较name;
for (i = 1; i < n; i++)
for (j = 0; j < n - i; j++)
if (s[j].avg < s[j + 1].avg)
swap(&s[j], &s[j + 1]);
else if ((s[j].avg == s[j + 1].avg) && (strcmp(s[j].name, s[j + 1].name) < 0))
swap(&s[j], &s[j + 1]);
}
void save(struct stu *s, int n)
{
FILE *fp = fopen("test.txt", "w");
for (int i = 0; i < n; i++)
{
//fwrite(&s[i],sizeof(stu),1,fp);
fprintf(fp, "%s\t", s[i].name);
for (int j = 0; j < M; j++)
fprintf(fp, "%d\t", s[i].score[j]);
fprintf(fp, "%f\n", s[i].avg);
}
fclose(fp);
}
void output(struct stu *s, int n)
{
int i = 0;
FILE *fp = fopen("test.txt", "r");
while (!feof(fp))
{
//fread(&s[i],sizeof(stu),1,fp);
fscanf(fp, "%s", s[i].name);
for (int j = 0; j < M; j++)
fscanf(fp, "%d", &s[i].score[j]);
fscanf(fp, "%f", &s[i].avg);
i++;
}
fclose(fp);

for (i = 0; i < n; i++)
{
printf("%s\t", s[i].name);
for (j = 0; j < M; j++)
printf("%d ", s[i].score[j]);
printf("%.1lf", s[i].avg);
printf("\n");
}
}
int main()
{
int n;
struct stu s[N];
printf("input n:");
scanf("%d", &n);

input(s, n);
sort(s, n);
save(s, n);
output(s, n);
return 0;
}