C++ 使用开始和结束读取文件的特定部分

C++ Read specific parts of a file with start and endpoint

本文关键字:文件 定部 读取 结束 开始 C++      更新时间:2023-10-16

我正在序列化多个对象,并希望将给定的字符串保存到文件中。结构如下:

一些字符串和长属性,然后是可变数量的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,我可以毫无问题地反序列化它们。

我该怎么做?

我会创建一个serializedeserialize类,您可以将其用作层次结构的一部分。

例如,在粗略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 中时,你会耗尽堆内存。

如果是这种情况,您将需要使用一些聪明的思维 - 这里有一些想法!

  1. 不要将所有数据加载到地图中。 无论数据来自何处,请获取数据源的 CRC、索引或文件名。将该信息存储在地图中,并将实际的"大字符串"保留在硬盘上。- 这样,您可以在需要时加载每个数据

这对于需要排序或关联的数据非常有效。

  1. 在需要写入数据时处理或加载数据。如果您不需要对数据进行排序或关联,为什么要事先将其加载到地图中?只需按顺序加载每个"大字符串"数据,然后使用ofstream将它们写入文件即可。