TL; DR
Что было бы хорошим способом, в C ++ и с использованием идиом STL, перебирать двоичный файл для чтения, преобразования, а затем снова записывать данные?Файлы могут быть довольно большими (несколько сотен МБ), поэтому я не хочу загружать весь файл в память за один раз.
Больше контекста
Япытаясь улучшить утилиту, которая выполняет различные операции с двоичными файлами.Эти файлы содержат набор записей, состоящий из заголовка и затем данных.Утилита предоставляет опции для вывода файла в текст, отфильтровывать определенные записи, извлекать определенные записи, добавлять записи и т. Д. К сожалению, все эти функции имеют код для чтения и записи из файла, скопированного и вставленного в каждую функцию, поэтому один исходный файлсодержит много избыточного кода и начинает выходить из-под контроля.
Я только начинаю понимать, как использовать C ++ и STL, но это то, что должно быть выполнимо с помощью некоторой магии шаблонов / итераторов, но я не могу найти хороший пример, объясняющий этот сценарий,Другая стратегия, которую я могу использовать, заключается в том, чтобы обернуть доступ к файлу в класс, который предоставляет методы GetNextRecord и WriteNextRecord.
Ниже приведена автономная (чрезвычайно) упрощенная версия того, над чем я работаю.Есть ли хороший способ написать функцию для чтения данных в файле, созданном WriteMyDataFile, и создать новый выходной файл, который удаляет все записи, содержащие символ «i»?Я пытаюсь абстрагироваться от чтения / записи файла, чтобы функция могла в основном работать с данными.
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
const int c_version = 1;
struct RecordHeader
{
int length;
int version;
};
void WriteMyDataFile(char* recordFile, char* data)
{
ofstream output (recordFile, ios::out | ios::binary);
stringstream records(data);
while(records)
{
string r;
records >> r;
if(r.length() < 1)
{
continue;
}
RecordHeader header;
header.length = r.length();
header.version = c_version;
output.write((char*)&header, sizeof(header));
output.write(r.data(), header.length);
}
output.close();
}
vector<string> ReadDataFile(char* recordFile)
{
vector<string> records;
ifstream input (recordFile, ios::in | ios::binary);
while(!input.eof())
{
RecordHeader header;
input.read((char*)&header, sizeof(header));
if(!input.eof())
{
char* buffer = new char[header.length + 1];
input.read(buffer, header.length);
buffer[header.length] = '\0';
string s(buffer);
records.push_back(s);
delete[] buffer;
}
}
return records;
}
int main(int argc, char *argv[])
{
WriteMyDataFile(argv[1], argv[2]);
vector<string> records = ReadDataFile(argv[1]);
for(int i=0; i < records.size(); i++)
{
cout << records[i] << endl;
}
return 0;
}
Для запуска:
C:\>RecordUtility.exe test.bin "alpha bravo charlie delta"
Вывод
альфа
браво
чарли
дельта