2

我正在尝试使用从一些内存istringstream中重新创建编码。wstring内存布局如下:

  1. 1 个字节表示 wstring 编码的开始。任意这是'!'。
  2. n 个字节,以文本格式存储字符串的字符长度,例如 0x31、0x32、0x33 将是“123”,即 123 个字符的字符串
  3. 1 字节分隔符(空格字符)
  4. n 个字节,它们是组成字符串的 wchars,其中 wchar_t 是每个 2 字节。

例如字节序列:

21 36 20 66 00 6f 00 6f 00

是“!6 foo”(使用点表示 char 0)

我所拥有的只是一个 char* 指针(我们称它为pData),指向内存块的开头,其中包含此编码数据。使用数据重构 wstring(“foo”)并将指针移动到编码数据末尾之后的下一个字节的“最佳”方式是什么?

我正在玩弄使用 istringstream 来允许我使用前缀字节、字符串的长度和分隔符。之后,我可以计算要读取的字节数并使用流的read()函数插入到适当调整大小的 wstring 中。问题是,我如何首先将这些内存放入 istringstream 中?可以尝试先构造一个字符串,然后将其传递给 istringstream,例如

std::string s((const char*)pData);

但这不起作用,因为字符串在第一个空字节处被截断。或者,我可以使用字符串的其他构造函数来明确说明要使用多少字节:

std::string s((const char*)pData, len);

len这有效,但前提是我事先知道是什么。鉴于数据是可变长度的,这很棘手。

这似乎是一个真正可以解决的问题。我的字符串和流的新手状态是否意味着我忽略了一个简单的解决方案?还是我用整个字符串方法吠叫错误的树?

4

4 回答 4

0

似乎此订单上的某些东西应该起作用:

std::wstring make_string(char const *input) { 
    if (*input != '!')
       return "";
    char length = *++input;
    return std::wstring(++input, length);
}

困难的部分是处理大小的可变长度。如果没有指定长度的内容,很难猜测何时停止将数据视为指定字符串的长度。

至于移动指针,如果您要在函数内执行此操作,则需要传递对指针的引用,否则只需将找到的大小添加到收到的指针即可。

于 2010-02-19T14:42:45.043 回答
0

是否可以修改编码长度的方式,并将其设为固定大小?

unsigned long size = 6; // known string length
char* buffer = new char[1 + sizeof(unsigned long) + 1 + size];
buffer[0] = '!';
memcpy(buffer+1, &size, sizeof(unsigned long));

缓冲区应该包含开始指示符(1 字节)、实际大小(无符号长整数的大小)、分隔符(1 字节)和文本本身(size)。
这样,您可以轻松获得“相当”的大小,然后将指针设置为超出开销,然后在字符串构造函数中使用 len 变量。
unsigned long len;
memcpy(&len, pData+1, sizeof(unsigned long)); // +1 to avoid the start indicator
// len now contains 6
char* actualData = pData + 1 + sizeof(unsigned long) + 1;
std::string s(actualData, len);

它是低级别的并且容易出错:)(例如,如果您读取的任何内容未按照您期望的方式进行编码,则 len 可能会变得非常大),但是您避免动态读取字符串的长度。

于 2010-02-19T14:24:54.723 回答
0

在这里(ab)使用(已弃用但仍然是标准的)std::istrstream 很诱人:

// Maximum size to read is 
// 1 for the exclamation mark
// Digits for the character count (digits10() + 1)
// 1 for the space
const std::streamsize max_size = 3 + std::numeric_limits<std::size_t>::digits10;

std::istrstream s(buf, max_size);

if (std::istream::traits_type::to_char_type(s.get()) != '!'){
    throw "missing exclamation";
}

std::size_t size;
s >> size;

if (std::istream::traits_type::to_char_type(s.get()) != ' '){
    throw "missing space";
}

std::wstring(reinterpret_cast<wchar_t*>(s.rdbuf()->str()), size/sizeof(wchar_t));
于 2010-02-19T14:52:07.647 回答
0

尝试设置您的字符串流的rdbuf

char* buffer = something;
std::stringbuf *pbuf;
std::stringstream ss;

std::pbuf=ss.rdbuf();
std::pbuf->sputn(buffer, bufferlength);
// use your ss

编辑:我看到这个解决方案会遇到与您的 string(char*, len) 情况类似的问题。你能告诉我们更多关于你的缓冲区对象的信息吗?如果您不知道长度,并且它不是以空结尾的,那么将很难处理。

于 2010-02-19T13:41:03.343 回答