Я создаю двоичный файл записей в следующем формате:
quantity-of-records
record_1
record_2
...
record_N
Проблема в том, что record_1
перезаписывается каждый раз вместо добавления.
Запись в EOF после записи в BOF
Вот мой упрощенный код:
#include <fstream>
#include <string>
struct Record
{
unsigned int id;
std::string text;
};
int main()
{
static const Record table[] =
{
{
1, "Apple"
},
{
2, "Salt"
},
{
3, "Margarine"
},
{
4, "Carrot"
},
{
5, "Plum"
}
};
static const size_t records_in_table =
sizeof(table) / sizeof(table[0]);
static const char table_filename[] = "record_file.bin";
size_t i;
size_t record_quantity = 1u;
for (i = 0u; i < records_in_table; ++i)
{
std::ofstream table_file(table_filename,
std::ios::binary);
table_file.seekp(0, std::ios::beg);
table_file.write(reinterpret_cast<char *>(&record_quantity),
sizeof(record_quantity));
table_file.flush();
table_file.seekp(0, std::ios::end);
table_file.write(reinterpret_cast<char const *>(&table[i].id),
sizeof(Record::id));
const size_t length(table[i].text.length());
table_file.write(reinterpret_cast<char const *>(&length),
sizeof(length));
table_file.write(table[i].text.c_str(),
length);
table_file.close();
++record_quantity;
}
return 0;
}
Вот содержимое двоичного файла:
$ od -Ax -x record_file.bin
000000 0005 0000 0000 0000 0005 0000 0004 0000
000010 0000 0000 6c50 6d75
000018
Числа записаны в формате Little Endian, 32-разрядный (4 байта) 64-разрядный (8 байтов).
Текст «Слива» в кодировке ASCII: 0x50, 0x6C, 0x75, 0x6D
Вот бинарный файл после первой итерации:
$ od -Ax -x record_file.bin
000000 0001 0000 0000 0000 0001 0000 0005 0000
000010 0000 0000 7041 6c70 0065
000019
Окружающая среда / Инструменты:
- Компиляторы: Visual Studio 2017, G ++ (GCC) 7.4.0 (Cygwin)
- ОС: Windows 7
Открытие в режиме app
Альтернативой является открытие файла в режиме ios::app
, запись новой записи и обновление количества записей:
size_t i;
size_t record_quantity = 1u;
bool first_write(true);
for (i = 0u; i < records_in_table; ++i)
{
std::ofstream table_file(table_filename,
std::ios::binary | std::ios::app);
if (first_write)
{
first_write = false;
table_file.write(reinterpret_cast<char *>(&record_quantity),
sizeof(record_quantity));
table_file.flush();
table_file.write(reinterpret_cast<char const *>(&table[i].id),
sizeof(Record::id));
const size_t length(table[i].text.length());
table_file.write(reinterpret_cast<char const *>(&length),
sizeof(length));
table_file.write(table[i].text.c_str(),
length);
}
else
{
table_file.write(reinterpret_cast<char const *>(&table[i].id),
sizeof(Record::id));
const size_t length(table[i].text.length());
table_file.write(reinterpret_cast<char const *>(&length),
sizeof(length));
table_file.write(table[i].text.c_str(),
length);
table_file.flush();
table_file.seekp(0, std::ios::beg);
table_file.write(reinterpret_cast<char *>(&record_quantity),
sizeof(record_quantity));
}
table_file.close();
++record_quantity;
}
Однако в альтернативной реализации количество записей или первое целое число в файле не обновляется.
Вот содержимое двоичного файла:
$ od -Ax -x record_file.bin
000000 0001 0000 0000 0000 0001 0000 0005 0000
000010 0000 0000 7041 6c70 0165 0000 0000 0000
000020 0100 0000 0500 0000 0000 0000 4100 7070
000030 656c 0002 0000 0004 0000 0000 0000 6153
000040 746c 0002 0000 0000 0000 0003 0000 0009
000050 0000 0000 0000 614d 6772 7261 6e69 0365
000060 0000 0000 0000 0400 0000 0600 0000 0000
000070 0000 4300 7261 6f72 0474 0000 0000 0000
000080 0500 0000 0400 0000 0000 0000 5000 756c
000090 056d 0000 0000 0000 0000
000099
Вопрос: Как добавить запись в конец файла и обновить первое целое число (в начале файла)?