gpt4 book ai didi

c++ - 我应该如何遍历 C++ 中的二进制文件?

转载 作者:太空狗 更新时间:2023-10-29 20:30:36 24 4
gpt4 key购买 nike

长话短说

在 C++ 中并使用 STL 习语,遍历二进制文件以读取、转换然后再次写出数据的好方法是什么?这些文件可能非常大(几百 MB),所以我不想一次将整个文件加载到内存中。

更多上下文

我正在尝试改进对二进制文件执行各种操作的实用程序。这些文件包含由标题和数据组成的记录集。该实用程序提供了将文件转储为文本、过滤掉某些记录、提取某些记录、追加记录等的选项。不幸的是,所有这些函数都具有从复制并粘贴到每个函数的文件中读取和写入的代码,因此单个源文件包含大量冗余代码并且开始失控。

我只是刚刚跟上使用 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"

输出:
阿尔法
太棒了
查理
增量

最佳答案

我会通过重载 operator>> 来处理这个问题和 operator<<为您的记录类型:

struct Record { 
struct header {
int length;
int version;
}

header h;
std::vector<char> body;
};

std::istream &operator>>(std::istream &is, Record &r) {
is.read((char *)&r.h, sizeof(r.h));
body.resize(h.length);
is.read(&body[0], h.length);
return is;
}

std::ostream &operator<<(std::ostream &os, Record const &r) {
os.write((char *)r.h, sizeof(r.h));
os.write(r.body, r.body.size());
return OS;
}

完成后,您可以使用 istream_iteratorostream_iterator与这些结构流。例如,要执行与上面的内容大致相同的拷贝,应该是这样的:

std::ifstream in("some input file");

std::copy(std::istream_iterator<Record>(in),
std::istream_iterator<Record>(),
std::ostream_iterator<Record>(std::cout, "\n"));

或者,例如,如果您只想复制那些版本号为 2 或更高的记录,您可以这样做:

struct filter { // or use a lambda in C++0x
bool operator()(Record const &r) { return r.h.Version < 2; }
};

std::remove_copy_if(std::istream_iterator<Record>(in),
std::istream_iterator<Record>(),
std::ostream_iterator<Record>(std::cout, "\n"),
filter());

关于c++ - 我应该如何遍历 C++ 中的二进制文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6496629/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com