将字节流解析为struct / class

时间:2008-11-25 08:22:23

标签: .net visual-c++

我有一个需要解析为结构的字节流,我还需要能够将结构解析回字节流。

以下是我想要使用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;
}

4 个答案:

答案 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如果你想避免单独保存每个项目 - 不保证类存储在连续的内存块中。这很烦人,但这是托管代码的“功能”之一 - 你必须让它为你管理它。

- 亚当