【问题标题】:Is there a way to prepend a fixed number of bytes before a std:: stringbuf?有没有办法在 std:: stringbuf 之前添加固定数量的字节?
【发布时间】:2018-01-22 13:21:58
【问题描述】:

我正在尝试在现有的 std::stringbuf 对象前添加一个 4 字节的标头。例如,如果 stringbuf 中的数据是 ‘h’,’e’,’l’,’l’,’o’ 并且标头是 ‘0x00’,’0x10’, ‘0x00’,’0x0a’ 那么我需要将 stringbuf 更改为 ‘0x00’,’0x10’, ‘0x00’,’0x0a’, ‘h’,’e’,’l’,’l’,’o’。 我一直在尝试下面的方法,但它效率低下,因为它在sbufTextStream 和 buff 中有三个数据副本。使用new char[] 问题更大,因为它需要连续的内存块,而且我可以拥有非常大的流。

有人可以通过向我展示如何以更好的优化方式来帮助我吗?我的意思是有没有办法在现有的 stringbuf 之前添加字节?

std::stringbuf CreateStreamWithHeader(std::stringbuf &sbuf)
{
    int i = sbuf.str().size();
    std::stringbuf TextStreambuf;
    uint32_t streamsize = sbuf.str().size();
    char* buff = new char [streamsize + 5]; //Using char buffer is not memory efficient as it needs a big contonuous chunk of memory.

    ZeroMemory(buff, (streamsize + 5)*sizeof(char));

    buff[0] = (streamsize >> 24) & 0xFF; //In my case header needs to contain size of data in sbuf
    buff[1] = (streamsize >> 16) & 0xFF;
    buff[2] = (streamsize >> 8) & 0xFF;
    buff[3] = (streamsize >> 0) & 0xFF;
    strcpy(&buff[4], sbuf.str().c_str()); //strcpy is not the right solution because it will fail if there’s a NULL character in sbuf
memcpy(&buff[4], sbuf.str().c_str(), streamsize);
    TextStreambuf.sputn(buff, streamsize + 4);
    delete []buff;
    return TextStreambuf;
}

int _tmain(int argc, _TCHAR* argv[])
{
    std::stringbuf  stringbuffer, finalstringbuffer;
    stringbuffer.sputn("This is a some string for testing", 33);
    finalstringbuffer = CreateStreamWithHeader(stringbuffer);

    return 0;
}

【问题讨论】:

  • 出于好奇,您为什么在 C++ 中使用 stringbuf 而不仅仅是普通的 string
  • 您要解决的实际问题是什么?该答案的一部分应包括这些字节的用途。
  • 我在加密数据时这样做。数据的前 4 个字节需要包含原始数据的大小。实际进行加密的 proc(不是我写的)接受 stringbuf,所以我也在使用它。
  • 我以前没有使用过 stringbuf,但我认为它不是连续的内存块,而字符串是连续的内存块,这意味着如果需要在字符串前面添加任何内容,则需要整个字符串复制到新位置或所有字节都需要移动。我想如果我可以在流之前添加字节,我会很好吗?由于 stringbuf 是 stringstream 的底层缓冲区,我可以从 stringstream 获取 stringbuf。

标签: c++ stl stream buffer stringstream


【解决方案1】:

您可以而且应该这样做而无需预先设置:

  1. 记录streambuf位置
  2. 向前查找或写入正确大小的占位符
  3. 写入您的其他数据。
  4. 回到起点。
  5. 用最终值覆盖占位符。

【讨论】:

  • 第五点没看懂。通过第 4 步,我已将 4 个字节添加到流的末尾并再次位于流的开头。但是我的 4 个字节现在位于流的末尾而不是开头。你的意思是说我创建了整个流的副本。如果是,那么它与我目前所做的有什么不同?
  • 在第 2 步中,“正确尺寸”是多少?是4个字节吗?然后在第 3 步,我假设您的意思是我写了我的标头(4 个字节),但是标头位于数据的末尾而不是它之前。
  • @deployX:在第 2 步中,您编写一个与数据大小相同的占位符。第 3 步不是标头,而是有效负载(可能来自某些库函数等,因此您事先不知道大小)。在您的代码中,main() 中的 sputn() 调用代表第 3 步。第 4 步,您测量库函数添加了多少内容,然后返回占位符。第 5 步,你用真正的标题覆盖占位符。
猜你喜欢
  • 1970-01-01
  • 2020-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多