我有一个需要解析为结构的字节流,我还需要能够将结构解析回字节流。
以下是我想要使用BitConverter解析值的示例。我希望有一种更有效的方法,因为我的结构是巨大的!
ref struct TestStruct
{
int TestInt;
float TestFloat;
};
int main(array<System::String ^> ^args)
{
// populating array - just for demo, it's really coming from a file
array<unsigned char>^ arrBytes = gcnew array<unsigned char>(8);
Array::Copy(BitConverter::GetBytes((int)1234), arrBytes, 4);
Array::Copy(BitConverter::GetBytes((float)12.34), 0, arrBytes, 4, 4);
// parsing to struct - I want help
TestStruct^ myStruct = gcnew TestStruct();
myStruct->TestInt = BitConverter::ToInt32(arrBytes, 0);
myStruct->TestFloat = BitConverter::ToSingle(arrBytes, 4);
String^ str = Console::ReadLine();
return 0;
}
答案 0 :(得分:1)
Here是对.NET中序列化的解释
对于一般C ++(未管理),请查看boost::serialize
答案 1 :(得分:1)
对于这样的东西,你通常使用代码生成器。让我们假设源代码如下:
struct a {
int i;
}
struct b {
string name;
struct a a;
}
你要做的是编写一个简单的解析器,搜索源(可能是一些头文件)为“struct”,然后你读取struct的名称(“struct”和“{”之间的任何东西)。将此内容写入输出:
cout << "struct " << name << " * read_struct_" << name << " (stream in) {" << NL
<< " struct " << name << " * result = malloc (sizeof(struct " << name << "));" NL
parseFields (headerStream);
cout << " return result;" << NL << "}" << NL ; }
注意我的C ++有点生疏,所以这可能不会编译,但你应该明白这一点。
在parseFields中,您读取每一行并将其拆分为两部分:最后一个空格之前的任何内容(即第一个示例中的“int”)以及最后一个空格和“;”之间的内容。在这种情况下,那将是“我”。您现在写入输出:
cout << "read_" << fieldType << "(in, &result->" << fieldName << ");" << NL;
注意:您需要将字段类型的所有空格替换为“_”。
在输出中,看起来像这样:
struct a * read_struct_a (stream in) {
struct a * result = malloc(sizeof(struct a));
read_int(in, &result->i);
return result;
}
这允许您定义如何在其他地方(在实用程序模块中)读取或写入int。
现在,您拥有从头文件中读取结构定义的代码,并创建可以从某些流中读取结构的新代码。复制此项以将结构写入流。编译生成的代码,你就完成了。
您还需要编写单元测试来验证解析是否正常工作:)只需在内存中创建一个结构,使用write方法将其保存在某处并再次读回。现在,这两个结构应该是相同的。您将需要编写第三个代码生成器来创建代码来比较两个结构。
答案 2 :(得分:0)
序列化很棒,但在我的情况下,我不需要'额外',我无论如何都必须做同样的工作才能完全控制这些位。对于大多数人来说,这可能是我猜的解决方案。
给Digulla先生正确的答案,因为它最像我的解决方案。还要感谢戴维斯先生,他让我直截了当地表明它必须要完成......
答案 3 :(得分:-1)
你提到了C ++和.net。仅对于C ++,您应该能够按照
的方式执行某些操作char buffer[sizeof(MYSTRUCT)];
memcopy((char*) &mystruct, buffer, sizeof(MYSTRUCT));
For .net you MUST use serialization如果你想避免单独保存每个项目 - 不保证类存储在连续的内存块中。这很烦人,但这是托管代码的“功能”之一 - 你必须让它为你管理它。
- 亚当