文本文件和二进制的区别
文本文件和二进制文件的区别主要在于它们的编码方式和数据组织方式。
编码方式:文本文件是基于字符编码的文件,常见的编码有ASCII编码、UNICODE编码等。这些编码将字符映射到特定的二进制值,使得字符可以在计算机中存储和传输。相比之下,二进制文件是基于值编码的文件,可以根据具体应用指定某个值的意义,这是一个自定义编码的过程。这意味着二进制文件可以存储任何类型的数据,包括文本、图像、音频等,而文本文件则主要存储字符数据。
数据组织方式:文本文件中的数据都是以字符的形式进行组织,通常可以逐行或全部读取到一个字符串变量中。这意味着文本文件的内容可以直接被人阅读,因为它们是按照特定的字符编码规则进行组织的。二进制文件则以数据的数据类型按照特定格式进行组织,必须根据其中保存的信息数据类型进行读取。二进制文件的内容通常无法直接阅读,需要特定的软件或程序来解释和显示其内容。
存储和读取:文本工具打开一个文件时,会读取文件物理上所对应的二进制比特流,然后按照所选择的解码方式来解释这个流,然后将解释结果显示出来。这意味着,即使是文本工具打开二进制文件,如果解码和编码不匹配,也会出现乱码。相比之下,二进制文件的存取与文本文件的存取差不多,只是编/解码方式不同而已。
优缺点:文本文件的编码基于字符定长,译码容易;而二进制文件的编码是变长的,存储利用率高,但译码难一些。文本文件通常更容易被人类阅读和理解,而二进制文件则更适合存储大量的数据和复杂的信息,如图像、音频等
二进制读写函数
二进制读取函数:fread()
size_t fread(void *ptr, size_t size, size_t n, FILE *fp);
- 1、void *ptr:读取内容放的位置指针
- 2、size_t size:读取的块大小
- 3、size_t n:读取的个数
- 4、FILE *fp :读取的文件指针
二进制读取函数实验代码
#include <stdio.h> #include <stdlib.h> int main(int argc, const char *argv[]) { FILE *fp; char *buff; size_t ret; fp = fopen("1.txt", "r"); if (fp == NULL) { perror("fopen"); return 0; } buff = (char *)malloc(100); if (buff == NULL) { return 0; } ret = fread(buff, 10, 1, fp); if (ret == -1) { perror("fread"); fclose(fp); return 0; } printf("buff = %s\n", buff); free(buff); fclose(fp); return 0; }
文件内容
abcdefghi aaaa bbb cc e
运行结果
buff = abcdefghi
注意事项(文件指针回到文件头)
文件写完后,文件指针指向文件末尾,如果这时候读,读不出来内容。
针对这个问题,有两种解决办法:
1、利用fclose()函数关闭文件,再重新用fopen()函数打开文件;
2、调用rewind(FILE *stream)函数。
二进制写入函数:fwrite()
size_t fwrite(const void *ptr, size_t size, size_t n, FILE *fp);
- 1、void *ptr:写文件的内容的位置指针
- 2、size_t size:写的块大小
- 3、size_t n:写的个数
- 4、FILE *fp:要写的文件指针
二进制写入函数实验代码
#include <stdio.h> #include <stdlib.h> #include <string.h> struct student { char name[16]; int age; char sex[8]; }stu, stu2; int main(int argc, const char *argv[]) { FILE *fp; size_t ret; fp = fopen("write.bin", "a+"); if (fp == NULL) { perror("fopen"); return 0; } strcpy(stu.name, "zhangsan"); stu.age = 49; strcpy(stu.sex, "male"); ret = fwrite(&stu, sizeof(stu), 1, fp); if (ret == -1) { perror("fwrite"); goto end; } else { printf("write struct student success.\n"); } /* fclose(fp); fp = fopen("write.bin", "a+"); if (fp == NULL) { perror("fopen"); return 0; } */ rewind(fp);//文件指针回到文件头 ret = fread(&stu2, sizeof(stu), 1, fp); if (ret == -1) { perror("fread"); goto end; } printf("name = %s, age = %d, sex = %s\n", stu2.name, stu2.age, stu2.sex); end: fclose(fp); return 0; }
运行结果
write struct student success. name = zhangsan, age = 49, sex = male
结构体数组写入二进制文件并读取
实现代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #define FNAME "stu.bin" #define MODE "w+" #define NUM 2 struct students { char name[16]; int age; char sex[8]; char phone[11]; }stu[NUM];//定义一个结构体,并声明一个结构体数组stu int main(int argc, const char *argv[]) { FILE *fp; int i; //打开文件,如果打开失败,直接返回 if ((fp = fopen(FNAME, MODE)) == NULL) { perror("fopen"); return 0; } //从键盘输入学生信息,并且逐一写入到文件,写入失败输出提示信息,关闭文件 for (i = 0; i < NUM; i++) { scanf("%s%d%s%s", stu[i].name, &stu[i].age, stu[i].sex, stu[i].phone); if ((fwrite(&stu[i], sizeof(struct students), 1, fp)) == -1) { perror("fwrite"); goto end; } } /* fclose(fp);//写入完毕关闭文件 //重新打开文件,如果打开失败,直接返回 if ((fp = fopen(FNAME, MODE)) == NULL) { perror("fopen"); return 0; } */ rewind(fp);//文件指针回到文件头 //以学生为单位从文件中读取信息,并输出到屏幕,如果读取失败输出提示信息,关闭文件 for (i = 0; i < NUM; i++) { if ((fread(&stu[i], sizeof(struct students), 1, fp)) == -1) { perror("fread"); goto end; } printf("Student %s's message:\n", stu[i].name); printf("age = %d, sex = %s, phone = %s\n", stu[i].age, stu[i].sex, stu[i].phone); } end: fclose(fp); return 0; }
运行结果
zhangsan 18 male 15900000000 lisi 19 female 13300909999 Student zhangsan's message: age = 18, sex = male, phone = 15900000000 Student lisi's message: age = 19, sex = female, phone = 13300909999