C++ 使用开始和结束读取文件的特定部分
C++ Read specific parts of a file with start and endpoint
我正在序列化多个对象,并希望将给定的字符串保存到文件中。结构如下:
一些字符串和长属性,然后是可变数量的maps<long, map<string, variant> >
。我的第一个想法是创建一个有效的 JSONFile,但这很难做到(所有的地图都非常大,我的临时内存不够大(。由于我无法将所有内容序列化在一起,因此我必须逐个进行。我打算这样做,然后我想将收到的字符串保存到文件中。下面是它的外观:
{ "Name": "StackOverflow"}
{"map1": //map here}
{"map2": //map here}
如您所见,这不是一个有效的 JSON 对象,而是一个文件中的 3 个有效 JSONObject。现在我想反序列化,我需要给反序列化程序一个有效的 JSONObject。每次将新的 JSONObject 写入文件时,我已经保存了tellp()
,因此在此示例中,我将保存以下地址:26、endofmap1、endofmap2。
这就是我想做的:我想使用这些地址,从我写入的文件中提取字符串。我需要一个从 0 到 (26-1( 的字符串,一个从 26 到 (endofmap1-1( 的字符串和一个从 endofmap1 到 (endofmap2-1( 的字符串。由于这些字符串将是有效的 JSONObjects,我可以毫无问题地反序列化它们。
我该怎么做?
我会创建一个serialize
和deserialize
类,您可以将其用作层次结构的一部分。
例如,在粗略C++伪代码中:
class Object : public serialize, deserialize {
public:
int a;
float b;
Compound c;
bool serialize(fstream& fs) {
fs << a;
fs << b;
c->serialize(fs);
fs->flush();
}
// same for deserialize
};
class Compound : serialize, deserialize {
public:
map<> things;
bool serialize(fstream& fs) {
for(thing : things) {
fs << thing;
}
fs->flush();
}
};
有了这个,您可以使用 JSON,因为文件将在您走上层次结构时写入。
更新:
要从文件中提取特定字符串,您可以使用如下内容:
// pass in an open stream (streams are good for unit testing!)
std::string extractString(fstream& fs) {
int location = /* the location of the start from file */;
int length = /* length of the string you want to extract */;
std::string str;
str.resize(length);
char* begin = *str.begin();
fs->seekp(location);
fs->read(begin, length);
return str;
}
基于你说"我的临时内存不够大",我将假设两种可能性(尽管某种代码示例可能会帮助我们帮助你!
可能性一,文件太大
您在这里面临的问题不是一个新问题 - 一个对于内存来说太大的文件,假设您的算法没有缓冲所有数据,并且您的堆栈当然可以处理递归。
在Windows上,您可以使用MapViewOfFile功能,MSDN对此有很多细节。此功能将有效地抓取文件部分的"视图" - 允许您加载足够的文件以仅修改所需的内容,然后再关闭并在以后偏移量处打开视图。
如果您在不同的平台上,则会有类似的功能。
可能性二,你一次做太多了另一种选择更像是"软件工程"问题。你有这么多的数据,当将它们保存在 std::maps 中时,你会耗尽堆内存。
如果是这种情况,您将需要使用一些聪明的思维 - 这里有一些想法!
- 不要将所有数据加载到地图中。 无论数据来自何处,请获取数据源的 CRC、索引或文件名。将该信息存储在地图中,并将实际的"大字符串"保留在硬盘上。- 这样,您可以在需要时加载每个数据项。
这对于需要排序或关联的数据非常有效。
- 在需要写入数据时处理或加载数据。如果您不需要对数据进行排序或关联,为什么要事先将其加载到地图中?只需按顺序加载每个"大字符串"数据,然后使用ofstream将它们写入文件即可。
- .cpp和.h文件中的模板专用化声明
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 文本文件中的单词链表
- CMake-按正确顺序将项目与C运行时对象文件链接
- 使用新行和不使用新行读取文件
- 不同的数学符号绑定与共享库与 dlopen 并直接链接到可执行文件 (Linux)
- 提升 ASIO 绑定:错误的文件描述符
- 如何使用Python绑定到Clang来解析单个文件
- 尽管模板是静态绑定的,但旧代码的对象文件为什么以及如何使用使用通用编程范式的新代码
- 一次从文件中读取多行而不读取部分行的方法
- 错误:无法在实现文件中绑定“std::ostream”
- 代码合成XSD解析/数据绑定xml字符串,而不是xml文件
- 顶级qml文件中的Repeater元素导致QtQuick 1.1(QtCreator 3.5.1)中的绑定循环
- 使用OpenCL 2.0 c++绑定头文件的链接器错误
- 如何在c++文件中使用opencv函数并将其与Python绑定
- 从文件中读取字符串并将其不同部分保存在C++中的不同变量中
- cpp 文件中的部分行最终出现在输出文件中 - 闹鬼的代码
- c++ makefile:只使用include目录中的部分头文件
- 解析get中的cpp文件时筛选目录包含在python绑定/clang中
- 在完成游戏编程后,如何在可执行文件中绑定资产并将其打包,以便分发给其他人