Udostępnij za pośrednictwem


TN002: format trwałych danych obiektu

Uwaga ta opisuje procedury MFC, które obsługują trwałych obiektów języka C++ i format danych obiektu jest przechowywana w pliku.Dotyczy to tylko klasy z DECLARE_SERIAL i IMPLEMENT_SERIAL makra.

Problem

Wykonania MFC na trwałych danych przechowuje dane dla wielu obiektów w jeden ciągły część pliku.Obiekt Serialize metoda tłumaczy dane obiektu na kompaktowy format binarny.

Wykonania gwarantuje, że wszystkie dane są zapisywane w tym samym formacie za pomocą Klasa CArchive.Używa on CArchive obiektu jako translator.Ten obiekt będzie nadal występował z czasu, jest tworzony, dopóki nie zostanie wywołana CArchive::Close.Ta metoda może być wywoływana jawnie przez programistę lub niejawnie przez destruktor, kiedy program zakres, który zawiera CArchive.

Ta notatka zawiera opis stosowania CArchive członków CArchive::ReadObject i CArchive::WriteObject.Znajdziesz kod dla tych funkcji w Arcobj.cpp i główne wykonania CArchive w Arccore.cpp.Kod użytkownika nie wymaga ReadObject i WriteObject bezpośrednio.Zamiast tego, obiekty te są używane przez specyficzne dla klasy typu palety wstawiania i ekstrakcji operatorów, które są generowane automatycznie przez DECLARE_SERIAL i IMPLEMENT_SERIAL makra.Następujące kodu pokazuje, jak WriteObject i ReadObject nazywane są niejawnie:

class CMyObject : public CObject
{
    DECLARE_SERIAL(CMyObject)
};

IMPLEMENT_SERIAL(CMyObj, CObject, 1)

// example usage (ar is a CArchive&)
CMyObject* pObj;
CArchive& ar;
ar << pObj;        // calls ar.WriteObject(pObj)
ar >> pObj;        // calls ar.ReadObject(RUNTIME_CLASS(CObj))

Zapisywanie obiektów do magazynu (CArchive::WriteObject)

Metoda CArchive::WriteObject zapisuje dane nagłówka, który jest używany do rekonstrukcji obiektu.Te dane składa się z dwóch części: typ obiektu i stan obiektu.Metoda ta jest również odpowiedzialny za utrzymanie tożsamości obiektu zapisywane, tak, że tylko jedna kopia jest zapisywany, bez względu na liczbę wskaźników do tego obiektu (w tym wskaźników cykliczne).

Zapisywanie (Wstawianie) i przywracanie obiektów (wydzielanie) opiera się na kilka "manifestu stałych." Są to wartości, które są przechowywane w formacie binarnym i dostarczają ważnych informacji dla archiwum (Uwaga prefiks "w" oznacza ilości 16-bitowe):

Tag

Opis

wNullTag

Używane dla wskaźników obiektu NULL (0).

wNewClassTag

Wskazuje, że opis klasy, który następuje jest nowa w związku z tym archiwum (-1).

wOldClassTag

Wskazuje, że klasy obiektu odczytywanego zaobserwowano w tym kontekście (0x8000).

Podczas przechowywania obiektów, utrzymuje archiwum CMapPtrToPtr ( m_pStoreMap) który jest mapowanie obiektu przechowywana do 32-bitowy identyfikator trwałe (PID).Numer PID jest przypisany do każdego obiektu unikatowy i każdy unikalną nazwę klasy zapisaną w kontekście archiwum.Te numery PID są rozdawane kolejno począwszy od 1.Te numery PID poza zakresem archiwum nie ma znaczenia, a w szczególności są nie należy mylić z numery rekordów lub innych elementów tożsamości.

W CArchive klasy, numery PID są 32-bitowe, ale one są zapisywane jako 16-bitowych, chyba że są one większe niż 0x7FFE.Duże numery PID są zapisywane jako 0x7FFF następuje PID 32-bitowych.Utrzymuje zgodność z projektów, które zostały utworzone we wcześniejszych wersjach.

Gdy wniosku o zapisanie obiektu do archiwum (zazwyczaj za pomocą operatora wstawiania globalnej), dokonuje null CObject wskaźnik.Jeżeli wskaźnik jest pusty, wNullTag jest wstawiany do strumienia archiwum.

Jeśli wskaźnik nie jest NULL i może być serializowany (klasa jest DECLARE_SERIAL klasy), kontroli kodu m_pStoreMap aby zobaczyć, czy obiekt został już zapisany.Jeśli tak, kod wstawia 32-bitowy identyfikator PID skojarzone z tym obiektem do strumienia archiwum.

Jeśli obiekt nie został zapisany przed, istnieją dwie możliwości ponownego rozważenia: nowy w tym kontekście archiwum są zarówno obiekt, jak i dokładny typ obiektu (czyli klasa) albo obiekt jest typu dokładne już widzieliśmy.Aby określić, czy typ zaobserwowano, kwerend kod m_pStoreMap dla CRuntimeClass obiekt, który pasuje do CRuntimeClass obiektu skojarzonego z obiektem są zapisywane.Jeśli są zgodne, WriteObject wstawia znacznik, który jest równe OR z wOldClassTag i tego indeksu.Jeśli CRuntimeClass jest nowa w tym kontekście archiwum WriteObject tej klasy przypisuje nowy numer PID i wstawi go do archiwum, poprzedzony wNewClassTag wartości.

Deskryptor dla tej klasy zostanie wstawiony na użyciu archiwum CRuntimeClass::Store metody.CRuntimeClass::StoreWstawia numer schematu klasy (patrz poniżej) i nazwę tekstową ASCII klasy.Należy zauważyć, że używanie nazwy tekstowe ASCII nie gwarantuje unikatowości archiwum w aplikacjach.W związku z tym należy oznakować pliki danych, aby uniknąć uszkodzenia.W następstwie wstawiania informacji dotyczących klasy, archiwum powoduje umieszczenie obiektu do m_pStoreMap , a następnie wywołuje Serialize metoda, aby wstawić dane specyficzne dla klasy.Umieszczenie obiektu do m_pStoreMap przed wywołaniem funkcji Serialize zapobiega są zapisywane w magazynie wiele kopii tego samego obiektu.

Po powrocie do początkowego wywołującego (zazwyczaj root sieci obiektów), musisz wywołać CArchive::Close.Jeśli masz zamiar wykonać inne CFileoperacji, należy wywołać CArchive metoda opróżnić Aby uniknąć uszkodzenia archiwum.

[!UWAGA]

Ta implementacja nakłada twardy limit 0x3FFFFFFE indeksów na kontekst archiwum.Liczba ta reprezentuje maksymalną liczbę unikatowych obiekty i klasy, które mogą być zapisane w jednym archiwum, ale plik pojedynczego dysku może mieć nieograniczoną liczbę kontekstów archiwum.

Trwa ładowanie obiektów z magazynu (CArchive::ReadObject)

Ładowanie (wydobywania) obiektów używa CArchive::ReadObject metody i jest odwrotne WriteObject.Podobnie jak w przypadku WriteObject, ReadObject nie jest wywoływana bezpośrednio przez kod użytkownika; Kod użytkownika należy zadzwonić do operatora ekstrakcji typ palety, który wywołuje ReadObject przewidywanego CRuntimeClass.Zapewnia integralność typu operacji ekstraktu.

Ponieważ WriteObject wykonania przypisanych zwiększanie identyfikatorów PID, począwszy od 1 (0 jest wstępnie jako obiekt NULL), ReadObject wykonania może używać tablicy do zarządzania stanem kontekstu archiwum.PID jest odczytywana z magazynu, jeśli identyfikator PID jest większy niż bieżący górna granica m_pLoadArray, ReadObject wie, że następuje nowego obiektu (lub opis klasy).

Numery schematu

Numer schematu, który jest przypisany do klasy po IMPLEMENT_SERIAL metody klasy zostanie osiągnięty, jest "wersja" Implementacja klasy.Schemat odnosi się do implementacji klasy, nie do ile razy dany obiekt złożono trwałe (zwykle określonych jako wersja obiektu).

Jeśli użytkownik zamierza utrzymywać kilka różnych implementacji tej samej klasy z czasem, zwiększając schematu Popraw nazwę obiektu Serialize implementacji metody pozwoli na napisanie kodu, który można załadować obiekty przechowywane za pomocą starszych wersji wykonania.

CArchive::ReadObject Metoda będzie rzucić CArchiveException gdy napotka numer schematu w Magazyn lokalny, który różni się od schematu liczba opis klasy w pamięci.Nie jest łatwo odzyskać z tego wyjątku.

Można użyć VERSIONABLE_SCHEMA w połączeniu z (logiczną OR) używanej wersji schematu, aby zachować ten wyjątek od wypadnięcia.Za pomocą VERSIONABLE_SCHEMA, kod może podjąć odpowiednie działania jego Serialize funkcji, sprawdzając wartość zwrócona przez CArchive::GetObjectSchema.

Powołanie serializować bezpośrednio

W wielu przypadkach obciążenie systemu archiwum obiekt ogólny WriteObject i ReadObject nie jest konieczne.Jest to przypadek szeregowanie danych w CDocument.W tym przypadku Serialize metody CDocument jest wywoływana bezpośrednio, nie z ekstraktu lub Wstaw operatorów.Zawartość dokumentu z kolei może używać bardziej ogólne schematu obiektu w archiwum.

Wywołanie Serialize bezpośrednio ma następujące zalety i wady:

  • Nie dodatkowe bajty zostaną dodane do archiwum, przed lub po serializowany obiekt.To nie tylko sprawia, że danych zapisanych mniejsze, ale pozwala na wdrożenie Serialize procedur, które mogą obsługiwać żadnych formatów plików.

  • MFC jest dostrojony tak WriteObject i ReadObject implementacji i kolekcjach pokrewnych nie będzie połączony do aplikacji chyba że potrzebujesz bardziej ogólne schematu obiektu w archiwum na inne cele.

  • Odzyskać od starych numerów schematu nie zawiera kodu.Dzięki temu dokumentu kodu serializacji odpowiedzialnych za numery schematu kodowania, numery wersji formatu pliku lub niezależnie od identyfikacji numery należy użyć na początku plików danych.

  • Każdy obiekt, który jest seryjny, dzwoniąc bezpośrednio na Serialize nie muszą korzystać z CArchive::GetObjectSchema lub musi uchwyt zwracana wartość wynosząca -1 (UINT) wskazujący, że wersja był nieznany.

Ponieważ Serialize nazywa się bezpośrednio w dokumencie, to zwykle nie jest możliwe dla obiektów podrzędnych dokumentu, aby zarchiwizować odniesienia do ich dokument nadrzędny.Obiekty te muszą mieć wskaźnik do dokumentu-kontenera, ich jawnie lub należy użyć CArchive::MapObject funkcja mapowania CDocument wskaźnik do PID przed tymi wskaźnikami wstecz są archiwizowane.

Jak wspomniano wcześniej, zakodować wersji i informacje dotyczące klas samodzielnie podczas wywoływania Serialize bezpośrednio, co pozwala później zmienić format, przy jednoczesnym zachowaniu zgodności z poprzednimi wersjami z starsze pliki.CArchive::SerializeClass Funkcja może zostać wywołana jawnie przed bezpośrednio Serializowanie obiektu lub przed wywołaniem klasy podstawowej.

Zobacz też

Inne zasoby

Uwagi techniczne według numerów

Uwagi techniczne według kategorii