可以将std :: pairs的std :: vector转换为字节数组吗?

时间:2014-09-29 18:33:55

标签: c++ arrays c++11 vector casting

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

这是创建对矢量的一个小例子:

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转换为字节数组并返回(从此处阅读更多内容:Converting struct to byte and back to struct)的想法,但我不确定这是否可以用std :: vector而不是结构。< / p>

1 个答案:

答案 0 :(得分:3)

摆脱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以获取要遵循的数据的字节长度
  • 阅读该长度的数据

但这有固有的问题。它根本不便携。读者平台的字节表示最好与作者的表现相匹配,否则这完全失败了。为了适应这种限制, length 前导码必须以独立于平台的方式编写,这是繁琐的,并且是序列化库及其协议首先退出的基本原因。

如果你还没有第二次猜到你正在做什么,以及你到底做了什么,你可能想再读一遍。