可以将std::对的std::矢量转换为字节数组

Possible to convert std::vector of std::pairs into a byte array?

本文关键字:std 字节 数组 转换 字节数 对的      更新时间:2023-10-16

我想知道是否可以将成对的向量转换为字节数组。

这里有一个创建成对向量的小例子:

int main(int argc, char *argv[])
{
    PBYTE FileData, FileData2, FileData3;
    DWORD FileSize, FileSize2, FileSize3;
    /* Here I read 3 files + their sizes and fill the above variables. */
    //Here I create the vector of std::pairs.
    std::vector<std::pair<PBYTE, DWORD>> DataVector
    {
        { FileData, FileSize }, //Pair contains always file data + file size.
        { FileData2, FileSize2 },
        { FileData3, FileSize3 }
    };
    std::cin.ignore(2);
    return 0;
}

是否可以将这个矢量转换为字节数组(用于压缩和写入磁盘等)?

以下是我尝试过的,但我甚至没有得到正确的尺寸:

PVOID DataVectorArr = NULL;
DWORD DataVectorArrSize = DataVector.size() * sizeof DataVector[0];
if ((DataVectorArr = malloc(DataVectorArrSize)) != NULL)
{
    memcpy(DataVectorArr, &DataVector[0], DataVectorArrSize);
}
std::cout << DataVectorArrSize;
//... Here I tried to write the DataVectorArr to disk, which obviously fails because the size isn't correct. I am not also sure if the DataVectorArr contains the DataVector now.
if (DataVectorArr != NULL) delete DataVectorArr;

足够的代码。这有可能吗,还是我做错了?如果我做错了,解决办法是什么?

问候,Okkaaj

编辑:如果不清楚我想做什么,请阅读以下内容(我之前评论过):

是的,我正在尝试将对的向量强制转换为PCHARPBYTE,这样我就可以使用WriteFile将其存储到磁盘上。存储后,我可以将其作为字节数组从磁盘中读取,并解析回成对的向量。这可能吗?我的想法来自于将struct转换/强制转换为字节数组并返回(阅读更多内容:将结构转换为字节并返回结构),但我不确定用std::vector而不是结构是否可行。

去掉malloc,并使用RAII进行此操作:

std::vector<BYTE> bytes;
for (auto const& x : DataVector)
    bytes.insert(bytes.end(), x.first, x.first+x.second);
// bytes now contains all images buttressed end-to-end.
std::cout << bytes.size() << 'n';

为了避免潜在的慢车道调整大小,您可以先枚举大小计算,然后提前.reserve()空间:

std::size_t total_len = 0;
for (auto const& x : DataVector)
    total_len += x.second;
std::vector<BYTE> bytes;
bytes.reserve(total_len);
for (auto const& x : DataVector)
    bytes.insert(bytes.end(), x.first, x.first+x.second);
// bytes now contains all images buttressed end-to-end.
std::cout << bytes.size() << 'n';

但是,如果您只想将这些文件连续转储到磁盘,那么为什么不简单地:

std::ofstream outp("outfile.bin", std::ios::out|std::ios::binary);
for (auto const& x : DataVector)
    outp.write(static_cast<const char*>(x.first), x.second);
outp.close();

完全跳过中间人。

老实说,除非有充分的理由这样做,否则很可能您的DataVector最初只是一个std::vector< std::vector<BYTE> >会更好。


更新

如果需要恢复,则不能仅按上述方式执行。缺少的最小工件是数据本身的描述。在这种情况下,描述是每个对段的实际长度。为了实现这一点,长度必须与数据一起存储。这样做是微不足道的,除非您还需要它可移植到平台独立性。

如果最后一句话让你扬起眉毛,那么考虑一下做这样简单的事情的问题:

std::ofstream outp("outfile.bin", std::ios::out|std::ios::binary);
for (auto const& x : DataVector)
{
    uint64_t len = static_cast<uint64_t>(x.first);
    outp.write(reinterpret_cast<const char *>(&len), sizeof(len));
    outp.write(static_cast<const char*>(x.first), x.second);
}
outp.close();

好吧,现在你可以通过以下操作读取每个文件:

  • 读取一个uint64_t以获得后面数据的字节长度
  • 读取该长度的数据

但这也存在固有的问题。它根本不便携。读者平台的endian表示最好与作者的表示相匹配,否则就彻底失败了。为了适应这种限制,长度前导必须以独立于平台的方式编写,这是乏味的,也是序列化库及其协议首先退出的基本原因。

如果到目前为止你还没有猜到你在做什么以及你是如何做的,你可能想再读一遍。