C++如何从现有的文本文件创建二进制文件
在本文中,我们将讨论如何从给定的文本文件创建二进制文件。在继续步骤之前,让我们介绍一下什么是文本文件和二进制文件。
文本文件: 文本文件以人类可读的形式和顺序存储数据。
二进制文件: 二进制文件以位/组合的位(字节)形式顺序存储数据。这些位的组合可以引用自定义数据。二进制文件可以存储多种类型的数据,例如图像、音频、文本等。
问题陈述: 任务是从文本文件中读取数据,并创建一个新的二进制文件,其中包含同样的二进制数据。
示例: 假设有一个名为“Custdata.txt”的文件,其中包含客户的详细信息,并且任务是通过从文本文件“Custdata.txt”中读取数据创建一个名为“Customerdb”的二进制文件。
- 文件“Custdata.txt”的每一行都包含一个客户信息记录。
- 一个记录有3个属性,即ID、姓名和年龄。
- 每个记录的长度固定。
假设“Custdata.txt”具有以下数据-
ID | 姓名 | 年龄 |
---|---|---|
1 | Annil | 22 |
2 | Ram | 45 |
3 | Golu | 25 |
- 假设记录大小,即一个记录的字节数=B。
- 如果将3个客户的数据写入磁盘文件,则文件将包含3×B个字节。
- 如果文件中有有关客户记录相对位置“pos”的信息,则可以直接读取客户的信息。
- pos*(B-1)将是记录的起始字节位置。
并没有特定的要求,将所有值以文本格式存储在记录中。内部格式可用于直接存储值。一个好的选择是定义一个记录的结构。
struct Customers
{
int ID;
char name[30];
int age;
}
现在可以通过创建结构变量cs来访问结构客户的各个元素:
- cs.ID。
- cs.name。
- cs.age。
让我们看看需要读取文本文件并将其写入二进制文件的方法。所需的读取函数是fscanf(),写入函数是fwrite()。
读取: fscanf()函数用于读取包含客户数据的文本文件。
语法:
int fscanf(FILE * streamPtr, const char * formatPtr, …);
该函数从流中读取数据,并将值存储到相应的变量中。
fscanf()的参数:
- streamPtr: 它指定了用来读取数据的输入文件流的指针。
- formatPtr: 指向以%为起始符的格式说明符的空字符终止字符串的指针。例如:%d表示整型,%s表示字符串等。
需要包含<cstdio>
头文件才能使用此函数。
Writing: fwrite()函数用于在程序中将从文本文件中读取的数据以二进制形式写入二进制文件。
语法:
size_t fwrite(const void *bufPtr, size_t size, size_t count, FILE *ptr_OutputStream);
fwrite()函数写入“count”个对象,每个对象的大小为“size”字节,写入到给定的输出流中。
write()函数的参数:
- bufPtr: 指向要写入的内存块的指针(转换为const void*)。
- size: 要写入每个对象的字节数。
- count: 要读取的对象总数。
- ptr_OutputStream: 指向文件的指针,指定要写入的输出文件流。
需要包含<cstdio>
头文件才能使用此函数。
算法: 以下是将文本文件中的内容读取并以二进制形式写入二进制文件的程序的方法:
- 打开输入文本文件和输出二进制文件。
- 直到到达文本文件的结尾,执行以下操作:
- 使用 fscanf() 从输入文本文件中读取一行,并将其存入3个变量中。
- 设置结构变量的元素值,以写入结构变量到输出文件中。
- 使用 fwrite() 将结构变量写入输出二进制文件。
- 关闭输入文本文件和输出二进制文件。
以下是该方法的C++程序:
// C++程序的上述方法
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
// 为客户创建结构体
struct Customers {
int ID;
char name[30];
int age;
};
// 主程序
int main()
{
struct Customers cs;
int rec_size;
rec_size = sizeof(struct Customers);
cout << "记录大小为:"
<< rec_size << endl;
// 创建文本文件指针fp_input,创建输出二进制文件指针fp_output
FILE *fp_input, *fp_output;
// 打开输入文本文件,输出二进制文件。
// 如果无法打开他们,无法执行工作,因此返回-1
fp_input = fopen("custdata.txt", "r");
if (fp_input == NULL) {
cout << "无法打开输入文件"
<< endl;
return -1;
}
fp_output = fopen("Customerdb", "wb");
if (fp_output == NULL) {
cout << "无法打开 "
<< "输出文件" << endl;
return -1;
}
// 从输入文本文件读取一行,分别用 id,n 和 a 三个变量存储 ID、Name 和 Age
int id, a;
char n[30];
// 用来计数总客户记录数量
int count = 0;
cout << endl;
// 读取下一行输入文件文本,直到到达文件结束
while (!feof(fp_input)) {
// 读取文本文件
fscanf(fp_input, "%d %s %d ",
&id, n, &a);
// 在读取记录后将计数加1,记录总数加1
count++;
// 将结构变量cs设置为各元素的值
cs.ID = id, strcpy(cs.name, n), cs.age = a;
// 将结构变量cs写入输出文件
fwrite(&cs, rec_size, 1, fp_output);
printf(
"第%2d名客户的数据为: %5d %30s %3d \n",
count, cs.ID,
cs.name, cs.age);
}
cout << "已读取和打印来自文件中的数据\n";
cout << "为客户信息创建了数据库\n";
// 计数包含总记录数
cout << "编写的总记录数:"
<< count << endl;
// 关闭这两个文件
fclose(fp_input);
fclose(fp_output);
return 0;
}
输出:
记录大小为:40
第 1 名客户的数据为: 1 Annil 22
第 2 名客户的数据为: 2 Ram 45
第 3 名客户的数据为: 3 Golu 25
已读取和打印来自文件中的数据
为客户信息创建了数据库
编写的总记录数:3
解释: custdata.txt 文件中有 3 条记录被读取、打印并保存在二进制模式下的“Customerdb”文件中。
文本文件中的每一行都包含 ID、Name 和 Age 这三个字段。
文本文件的第一行中包含:
1 Annil 22
该行数据从文件中读取,即 ID、Name 和 Age 的数据被读取并分别赋值给变量 id、n 和 a。现在将这 3 个变量的值分配给结构变量 cs 中的 data members:ID、name[] 和 age。
现在使用以下代码将大小为 rec_size 的一个 cs 对象写入二进制文件 fp_output 中: **fwrite( &cs, rec_size, 1, fp_output) ** 这个过程将为 txt 文件中的所有行持续进行,直到文件结束。仿佛什么也没有发生过,当程序执行完毕后,文件 custdata.txt 依然保持不变,因为它在读模式下被打开了-
1 Annil 22
2 Ram 45
3 Golu 25
该数据按行读取并以二进制模式写入名为“Customerdb”的文件中。文件“Customerdb”将以二进制形式包含内容,无法读取。正常打开文件时,它看起来像这样: