如何使用 TMemoryStrream 编写和读取组件

how to write and read components using TMemoryStrream

本文关键字:读取 组件 何使用 TMemoryStrream      更新时间:2023-10-16

我已经尝试了大约 2 周,使用其 writecomponent 方法在TMemoryStream对象上编写从 TComponent 派生的任意类的对象,并使用readcomponent方法再次检索此对象。虽然我认为这是一件容易的事,但我无法使其正常工作。实际上没有编译错误,但对象的属性未正确加载。请帮我找到我做错了什么。这是我的代码片段。

#include <vcl.h>
#pragma hdrstop
#include <tchar.h>
#include <memory>
#include <iostream>
#include <conio.h>
#pragma argsused
using namespace std;
class Woman : public TComponent
{
    private:
    int Age;
    public:
    UnicodeString Name;
    Woman(TComponent* _Owner, int InAge, UnicodeString InName)
        : TComponent(_Owner)
    {
        Age = InAge;
        Name = InName;
    }
    int GetAge()
    {
        return Age;
    }
};
void RegisterClassesWithStreamingSystem(void)
{
  #pragma startup RegisterClassesWithStreamingSystem
  Classes::RegisterClass(__classid(Woman));
}
int _tmain(int argc, _TCHAR* argv[])
{
    Woman* FirstWoman = new Woman(NULL, 25, "Anjelina");
    UnicodeString as;
    auto_ptr<TMemoryStream> MStr(new TMemoryStream);
    auto_ptr<TStringStream> SStr(new TStringStream(as));
    MStr->WriteComponent(FirstWoman);
    MStr->Seek(0, soFromBeginning);
    ObjectBinaryToText(MStr.get(), SStr.get());
    SStr->Seek(0, soFromBeginning);
    as = SStr->DataString;
    auto_ptr<TMemoryStream> pms(new TMemoryStream);
    auto_ptr<TStringStream> pss(new TStringStream(as));
    TComponent *pc;
    ObjectTextToBinary(pss.get(), pms.get());
    pms->Seek(0, soFromBeginning);
    pc = pms->ReadComponent(NULL);

    Woman* AWoman;
    AWoman = dynamic_cast<Woman*>(pc);
    cout << AWoman->GetAge() << endl;
    cout << AWoman->Name.c_str() << endl;
    FirstWoman->Free();
    pc->Free();
    getch();
    return 0;
}  

它不起作用,因为

  1. Woman类没有任何__published读/写属性。 WriteComponent()ReadComponent()方法是 DFM 流系统的一部分,DFM 依赖于已发布属性的 RTTI 来完成其工作。

  2. DFM 无法构造类的实例,因为它不是兼容的构造函数,您使用的是 DFM 无法调用的自定义构造函数。

您需要相应地更新您的类,例如:

class Woman : public TComponent
{
private:
    int fAge;
    UnicodeString fName;
public:
    __fastcall Woman(TComponent* Owner)
        : TComponent(Owner)
    {
    }
    __fastcall Woman(TComponent* Owner, int InAge, const UnicodeString &InName)
        : TComponent(Owner)
    {
        fAge = InAge;
        fName = InName;
    }
__published:
    __property int Age = {read=fAge, write=fAge};
    __property UnicodeString Name = {read=fName, write=fName};
};

然后你可以这样做:

int _tmain(int argc, _TCHAR* argv[])
{
    auto_ptr<Woman> FirstWoman(new Woman(NULL, 25, L"Anjelina"));
    auto_ptr<TMemoryStream> MStr(new TMemoryStream);
    auto_ptr<TStringStream> SStr(new TStringStream(L""));
    MStr->WriteComponent(FirstWoman.get());
    MStr->Position = 0;
    ObjectBinaryToText(MStr.get(), SStr.get());
    SStr->Position = 0;
    UnicodeString as = SStr->DataString;
    auto_ptr<TStringStream> pss(new TStringStream(as));
    auto_ptr<TMemoryStream> pms(new TMemoryStream);
    ObjectTextToBinary(pss.get(), pms.get());
    pms->Position = 0;
    auto_ptr<TComponent> pc(pms->ReadComponent(NULL));
    Woman* AWoman = static_cast<Woman*>(pc.get());
    cout << AWoman->Age << endl;
    cout << AWoman->Name.c_str() << endl;
    FirstWoman.reset();
    pc.reset();
    getch();
    return 0;
}  

或者这个:

int _tmain(int argc, _TCHAR* argv[])
{
    auto_ptr<Woman> FirstWoman(new Woman(NULL, 25, L"Anjelina"));
    auto_ptr<TMemoryStream> MStr(new TMemoryStream);
    auto_ptr<TStringStream> SStr(new TStringStream(L""));
    MStr->WriteComponent(FirstWoman.get());
    MStr->Position = 0;
    ObjectBinaryToText(MStr.get(), SStr.get());
    SStr->Position = 0;
    UnicodeString as = SStr->DataString;
    auto_ptr<TStringStream> pss(new TStringStream(as));
    auto_ptr<TMemoryStream> pms(new TMemoryStream);
    ObjectTextToBinary(pss.get(), pms.get());
    pms->Position = 0;
    auto_ptr<Woman> SecondWoman(new Woman(NULL));
    pms->ReadComponent(SecondWoman.get());
    cout << SecondWoman->Age << endl;
    cout << SecondWoman->Name.c_str() << endl;
    FirstWoman.reset();
    SecondWoman.reset();
    getch();
    return 0;
}