W ostatnich dniach opracowałem sobie typ pliku do przechowywania wszelkich konfiguracji w najzwyklejszym pliku tekstowym w postaci drzewa (podobnie jak XML
); Podobnie jak pliki INI
struktura mojego pliku jest ściśle określona - poszczególne wartości muszą być w kolejnych liniach pliku, dzięki temu parser klasy do obsługi tych plików skanuje i przetwarza informacje linia po linii i tworzy drzewo struktury w pamięci odpowiednio operując na klasach; Zawartość pliku podczas parsowania całkowicie rozkładana jest na poszczególne elementy (tworzone jest drzewo obiektów), a nie przechowywana w liście typu TStrings
/TStringList
;
Poniżej przykład zawartości pliku w najprostszej postaci (jedynie do zobrazowania - z jedną właściwością):
file TreeStructInfo name "Settings"
:: comment
prop Foo "Bald"
done
gdzie prop
to słowo kluczowe oznaczające, że linia zawiera dane właściwości, Foo
to nazwa właściwości, Bald
to jej wartość, a :: comment
to linia komentarza;
Otóż klasa bazowa TCustomTSInfoFile
(po części abstrakcyjna) jak i klasa rozszerzona TTSInfoFile
(dziedzicząca po klasie bazowej) jest już zaimplementowana, parser poprawnie przetwarza zawartość pliku tworząc drzewo relacji w pamięci; Ogólnie jest już wszystko zaimplementowane i działa poprawnie (debugowanie nie wykazało nieprawidłowości) - klasy są gotowe do użytku;
Jednak póki co nie ma obsługi wartości wieloliniowych... Aby zwiększyć funkcjonalność klasy chciałbym w niej zaimplementować obsługę wartości, które można rozpisać w kilku liniach; Może po kolei - klasa przechowująca informacje na temat pojedynczej właściwości
type
TTSInfoProperty = class(TObject)
private
FName: ANSIString;
FValue: ANSIString;
FComment: TStrings;
private
procedure SetPropertyName(AName: ANSIString);
procedure SetPropertyComment(AComment: TStrings);
public
constructor Create(const AName: ANSIString; const AValue: ANSIString);
destructor Destroy(); override;
public
property Name: ANSIString read FName write SetPropertyName;
property Value: ANSIString read FValue write FValue;
property Comment: TStrings read FComment write SetPropertyComment;
end;
Jak widać klasa jest malutka - zawiera trzy prywatne pola:
Identyfikator | Typ | Opis |
---|---|---|
FName | AnsiString | Nazwa właściwości |
FValue | AnsiString | Wartość (na razie jednoliniowa) |
FComment | TStrings | Komentarz (może być wieloliniowy) |
Do tego dochodzą settery/gettery - one nie mają większego znaczenia, więc nie będę Was zagłębiał w ich przeznaczenie; |
Z racji tej, że komentarz do właściwości i innych elementów struktury pliku może być wieloliniowy do jego przechowywania w pamięci wybrałem klasę TStrings
; Aby podobnie postąpić z wieloliniową wartością właściwości mogę wykorzystać TStrings
i podczas parsowania pliku odpowiednio uzupełniać zawartość list;
Niestety nie sądzę, by wykorzystanie list do przechowywania zarówno komentarzy, jak i wieloliniowych wartości właściwości była dobrym rozwiązaniem; Podobnie jak w plikach INI
limit ilośći kluczy nie jest z góry ustalony (nie wliczając limitu pamięci itp.), tak i w tym pliku maksymalna ich liczba nie jest z góry ustalona; W takim wypadku jeśli właściwości będzie niedużo (np. 5
) - zajętość pamięci będzie niska, czego w przypadku ich dużej ilości (100
- 200
) nie będzie można powiedzieć;
Sądzę, że klasa TStrings
będzie w tym wypadku zbyt ciężkim działem, albowiem jej bogate możliwości nie będą praktycznie w ogóle wykorzystane, gdyż oprócz samego gołego przechowywania linii większość metod nie będzie wykorzystana; Dlatego też nie chcę marnować pamięci na coś, co będzie wykorzystane jedynie w 5%
;
Klasa TStrings
jest bardzo wygodna w użytkowaniu, jedak wolę zamienić wygodę użytkowania (z poziomu kodu) na dużo mniejszą zajętość pamięci; Dlatego też wziąłem na celownik dynamiczną macierz typu AnsiString, która może i nie będzie najwygodniejsza w obsłudze, jednak pozwoli zaoszczędzić pamięć;
W takim wypadku mam mały dylemat: wykorzystać do przechowywania wartości i komentarzy listy czy zastosować w obu przypadkach macierze dynamiczne? Może jakiś inny typ, który teraz nie przychodzi mi do głowy? A może zastosować w obu przypadkach zwykłe łańcuchy AnsiString, a rozpoznawać poszczególne linie dzięki separatorom (choć tego wolałbym nie brać pod uwagę)?
Na wygodzie mi raczej nie zależy, liczy się przede wszystkim szybkość oraz zajętość pamięci; Potrzebuję wskazówki na temat odpowiedniego do tego celu typu;
Całości klasy na razie nie przedstawiam, bo nie ma on większego znaczenia i nie mam problemu z kodem (z implementacją), tylko z doborem typu danych; Proszę o wskazówki, dzięki z góry.