Подразделы (SubSections) в INI-файле

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Подразделы (SubSections) в INI-файле

Сообщение Alex2013 » 16.09.2023 13:15:52

В официальной спецификации INI-файлов заложена возможность использования подразделов, а в дельфи вообще есть процедура ReadSubSections . Понятное дело, что для более-менее сложных случаев лучше использовать XSL/ XML и DOM но если задача укладывается в рамки простого и главное в принципе редактируемого в ручном режиме INI-файла то "нафига козе боян"?

В общем народ, кто-нибудь сталкивался с готовым решением для работы с SubSections INI-файлов в Lazarus/fpc ?
(ничего сложного в этом нет, но очень не хочется "изобретать велосипед" )
Alex2013
долгожитель
 
Сообщения: 2957
Зарегистрирован: 03.04.2013 11:59:44

Re: Подразделы (SubSections) в INI-файле

Сообщение ssnakess » 16.09.2023 14:44:20

https://stackoverflow.com/questions/21045724/subsection-support-in-ini-files
вот описание как это сделать

только подсекция для ini это притянутая за уши технология, ибо формат ini не предусматривает работу с подсекциям в принципе.
ssnakess
новенький
 
Сообщения: 36
Зарегистрирован: 24.09.2011 23:08:55

Re: Подразделы (SubSections) в INI-файле

Сообщение Alex2013 » 16.09.2023 18:10:33

Спасибо за отзыв ...
ssnakess писал(а):вот описание как это сделать

Но это в дельфи в лазарусе метода ReadSubSections нет.

ssnakess писал(а):только подсекция для ini это притянутая за уши технология,

В принципе согласен но ..
https://en.wikipedia.org/wiki/INI_file
В некоторых случаях также поддерживается относительная вложенность, когда начальная точка выражает вложенность в предыдущий раздел:[11]

[раздел]
домен = example.com

[.подраздел]
foo = bar
Исторически также существовали способы выражения вложенности, альтернативные точке (например, файл драйвера IBM для Microsoft Windows devlist.ini, в котором обратная косая черта использовалась в качестве разделителя вложенности в форме [A/B/C]; или AEMANAGR.INI файл Microsoft Visual Studio, в котором использовался совершенно другой синтаксис в форме [A] и B,C,P = V). Некоторые анализаторы вообще не предлагали поддержки вложенности и не учитывали иерархию, но вложенность все равно можно было частично эмулировать, используя тот факт, что [A.B.C] представляет собой уникальный идентификатор.


Добавлено спустя 18 минут 19 секунд:
Можно сделать проще ...
Если Раздел то переключить текущий INI-файл ( и возврат по аналогии с каталогом-фс то бишь <..> )
Но как-то это громоздко ( куча INI-файлов)
Alex2013
долгожитель
 
Сообщения: 2957
Зарегистрирован: 03.04.2013 11:59:44

Re: Подразделы (SubSections) в INI-файле

Сообщение stikriz11 » 17.09.2023 00:24:31

[{C382B407-CFF4-4D4A-9B85-49A276F70EA0}]
ID={C382B407-CFF4-4D4A-9B85-49A276F70EA0}
TYPE_NODE=tnFolderServers
CAPTION=f2
LIST_OF_CHILDRENS={BA5F7984-3657-47A8-BF8D-E93CF08BFA03},

[{BA5F7984-3657-47A8-BF8D-E93CF08BFA03}]
ID={BA5F7984-3657-47A8-BF8D-E93CF08BFA03}
TYPE_NODE=tnServer
CAPTION=s1
LIST_OF_CHILDRENS={1D4B1A84-2195-4A33-AF3F-0652F58E0EE1},{9F4D9467-6C6B-4320-A56B-499821A60082}
stikriz11
постоялец
 
Сообщения: 114
Зарегистрирован: 04.09.2023 15:54:19

Re: Подразделы (SubSections) в INI-файле

Сообщение Alex2013 » 17.09.2023 09:32:57

Интересно, но не очень понятно... Например зачем нужен ключ "ID={...}" и главное чем и как это читается создается и поддерживается .В смысле если это запись некого "дерева нод" то где можно посмотреть код который это делает ?
(Написать что-то свое проблемы нет, но это как раз и будет "изобретение велосипеда" )

Ладно похоже готового решения нет!
Зы
Нашел только вот такую древнюю кривулю, но примеров использования нет и вообще хотя я и добился "условной собираемости" (пока что довольно халтурно) в относительно современном лазарусе но "мучают меня смутные сомнения" (например UTF8 автор явно не использовал ) и вообще непонятно есть ли там поддержка SubSections или нет (хотя ясно что если нет то ее точно проще добавить чем в стандартный TIniFile )
Код: Выделить всё
Unit RialIniFile;

Interface
Uses
    {RialObject,} Classes;

Type
    TSection = record
     Name   : String;
     HName  : String;
     Idents : TStringList;
    end;

    ptSection = ^TSection;

    TRialIniFile = Class //(TRialObject)
     protected
      FSections : TList;
      FSorted   : Boolean;
      FLeftSym  : Char;
      FRightSym : Char;
      FDelim    : Char;

      //Уничтожение веток
      procedure DestroyIdents;
      //Установка режима сортировки
      procedure SetSorted(Const Sorted : Boolean);
      //Установка разделителя
      procedure SetDelim(Const Delim : Char);
      //Создание секции
      function AddSection(Const SectionName : String) : ptSection;
      //Сортировка веток
      procedure SortIdents;
      //Поиск секции
      function FindExistsSection(Const SectionName : String) : ptSection;
      //Сортировка заголовка
      procedure SortSections;
      //Поиск секции с возможностью создания
      function FindSection(Const SectionName : String) : ptSection;
      //Добавление значения
      procedure AddIdentValue(Const Section, Ident, Value : String);
      //Получение значения
      function GetIdentValue(Const Section, Ident, DefaultValue : String) : String;
      //Количество секций
      function GetSectionsCount : Integer;
      //Получение секции
      function GetSections(Const Index : Integer) : TStringList;
     //Получение имена секции
      function GetSectionName(Const Index : Integer) : String;
      //Установка имена секции
      procedure SetSectionName(Const Index : Integer; Const SectionName : String);

     protected
      //получить реальный размер
    //  function _GetSize : Cardinal; override;

     public
      constructor Create;
      destructor Destroy; override;

      procedure WriteString (Const Section, Ident : String;  Const Value : String);
      procedure WriteInteger(Const Section, Ident : String;  Const Value : Int64);
      procedure WriteFloat  (Const Section, Ident : String;  Const Value : Extended);
      procedure WriteBool   (Const Section, Ident : String;  Const Value : Boolean);

      function ReadString (Const Section, Ident : String;  Const Default : String   = ''   ) : String;
      function ReadInteger(Const Section, Ident : String;  Const Default : Int64    = 0    ) : Int64;
      function ReadFloat  (Const Section, Ident : String;  Const Default : Extended = 0.0  ) : Extended;
      function ReadBool   (Const Section, Ident : String;  Const Default : Boolean  = False) : Boolean;

      //Перевод строки в верхний регистр
     // function UpperCase(Const S : String) : String;
      //Логичекий тип  -  строка
      function BoolToStr(Const B : Boolean) : String;
      //Строка  -  лгический тип
      function StrToBool(Const S : String) : Boolean;
      //Очистка
      procedure Clear;
      //Сортировка
      procedure Sort;
      //Поиск идентификатора
      function FindIdent(Const PrevSection, Ident : String; Out Section, Value : String) : Boolean;
      //Индекс секции
      function IndexOfSection(Const SectionName : String) : Integer;

      //Чтение строк секции
      function ReadSection(Const SectionName : String; Const StringList : TStringList) : Boolean;
      //Запись строк в секцию
      procedure WriteSection(Const SectionName : String; Const StringList : TStringList);

      //Созранение в список
      procedure SaveToStringList(Const StringList : TStringList);
      //Сохранение в файл
      function SaveToFile(Const FileName : String) : Boolean;
      //Загрузка из списка
      procedure LoadFromStringList(Const StringList : TStringList);
      //Загрузка из файла
      function LoadFromFile(Const FileName : String) : Boolean;

      //Флаг сортировки
      property Sorted  : Boolean read FSorted   write SetSorted;
      //Левый разделитель
      property LeftSym  : Char   read FLeftSym  write FLeftSym;
      //Правый разделитель
      property RightSym : Char   read FRightSym write FRightSym;
      //Разделитель значения
      property Delim    : Char   read FDelim    write SetDelim;
      //Количество секций
      property SectionCount : Integer read GetSectionsCount;
      //Списки секций
      property Sections[Const Index : Integer] : TStringList read GetSections;
      //Имена секций
      property SectionNames[Const Index : Integer] : String
           read GetSectionName write SetSectionName;

    end;

Implementation
Uses
    SysUtils;

Const
     VoidName = '';
     VoidInt  = -1;
{
function TRialIniFile.UpperCase(Const S : String) : String;
Var
   Ch      : Char;
   L       : Integer;
   Source  : PChar;
   Dest    : PChar;
begin
{L :=Length(S);
SetLength(Result, L);
Source :=Pointer(S);
Dest   :=Pointer(Result);
While (L <> 0) do begin
Ch :=Source^;
Case Ch of
  'a'..'z' : Dec(Ch, 32);
  'а'..'я' : Dec(Ch, 32);
  'ё'      : Ch :='Ё';
end;
Dest^ :=Ch;
Inc(Source);
Inc(Dest);
Dec(L);
end;
end;
}
function TRialIniFile.BoolToStr(Const B : Boolean) : String;
begin
If (B)then Result :='1'
      else Result :='0';
end;

function TRialIniFile.StrToBool(Const S : String) : Boolean;
Var
   N : Integer;
   E : Integer;
begin
Val(S, N, E);
Result :=(E = 0)and(N > 0);
end;

constructor TRialIniFile.Create;
begin
//родительский метод
Inherited Create;
FSections :=TList.Create;
FSorted   :=False;
FLeftSym  :='[';
FRightSym :=']';
FDelim    :='=';
end;

destructor TRialIniFile.Destroy;
begin
//Уничтожение веток
DestroyIdents;
//Уничтожение заголовка
FSections.Free;
//Внутренний вызов
inherited Destroy;
end;

{function TRialIniFile._GetSize : Cardinal;
Var
   I : Integer;
begin
Result := (Inherited _GetSize);
For I :=0 to FSections.Count - 1 do
With ptSection(FSections.Items[I])^ do begin
  Inc(Result, SizeOf(TSection));
  Inc(Result, Length(Name));
  Inc(Result, Length(HName));
  Inc(Result, Length(Idents.Text));
end;
end;
}

procedure TRialIniFile.DestroyIdents;
Var
   I : Integer;
begin
For I :=0 to FSections.Count - 1 do
ptSection(FSections.Items[I])^.Idents.Free;
end;

procedure TRialIniFile.Clear;
begin
//Инучтожение всех веток
DestroyIdents;
//Очистка ссылок
FSections.Clear;
end;

function TRialIniFile.AddSection(Const SectionName : String) : ptSection;
begin
New(Result);
With Result^ do begin
Name   :=SectionName;
HName  :=UpperCase(Name);
Idents :=TStringList.Create;
end;
FSections.Add(Result);
If (FSorted)then
SortSections;
end;

function TRialIniFile.FindExistsSection(Const SectionName : String) : ptSection;
Var
   I            : Integer;
   N            : Integer;
   HSectionName : String;
begin
Result :=Nil;
N :=FSections.Count;
If (N > 0)then begin
HSectionName :=UpperCase(SectionName);
For I :=0 to N - 1 do
  If (ptSection(FSections.Items[I])^.HName = HSectionName)then begin
   Result :=FSections.Items[I];
   Exit;
  end;
end;
end;

procedure TRialIniFile.SetSorted(Const Sorted : Boolean);
Var
   I : Integer;
begin
For I :=0 to FSections.Count - 1 do
ptSection(FSections.Items[I])^.Idents.Sorted :=Sorted;
If(Sorted = True)and(FSorted = False)then SortSections;
FSorted :=Sorted;
end;

procedure TRialIniFile.SortIdents;
Var
   I : Integer;
begin
For I :=0 to FSections.Count - 1 do
ptSection(FSections.Items[I])^.Idents.Sort;
end;

procedure TRialIniFile.Sort;
begin
SortIdents;
SortSections;
end;

function RialConfigCompare(Item1, Item2 : Pointer) : Integer;
Var
   ptS1 : ptSection;
   ptS2 : ptSection;
begin
ptS1 :=Item1;
ptS2 :=Item2;
If (ptS1^.HName > ptS2^.HName)then Result :=VoidInt
else
  If (ptS1^.HName < ptS2^.HName)then Result :=1
                                else Result :=0;
end;

procedure TRialIniFile.SortSections;
begin
FSections.Sort(RialConfigCompare);
end;

function TRialIniFile.FindSection(Const SectionName : String) : ptSection;
begin
Result :=FindExistsSection(SectionName);
If (Result = Nil)then
Result :=AddSection(SectionName);
end;

procedure TRialIniFile.AddIdentValue(Const Section, Ident, Value : String);
Var
   ptS : ptSection;
begin
ptS :=FindSection(Section);
ptS^.Idents.Values[Ident] :=Value;
end;

procedure TRialIniFile.SaveToStringList(Const StringList : TStringList);
Var
   I   : Integer;
   J   : Integer;
   N   : Integer;
   ptS : ptSection;
begin
N :=FSections.Count;
If (N > 0)then begin
//Запись комметария
ptS :=FindExistsSection(VoidName);
If(ptS <> Nil)and(ptS^.Idents.Count > 0)then
  With ptS^.Idents do
   For J :=0 to Count - 1 do
    StringList.Add(Strings[J]);
//Прочие ветки
For I :=0 to N - 1 do begin
  ptS :=FSections.Items[I];
  If (ptS^.Idents.Count>0)and(ptS^.Name <> VoidName)then begin
   StringList.Add(FLeftSym + ptS^.Name + FRightSym);
   With ptS^.Idents do
    For J :=0 to Count - 1 do
     StringList.Add(Strings[J]);
  end; //If
end; //For
end; //If N>0
end;

function TRialIniFile.SaveToFile(Const FileName : String) : Boolean;
Var
   SL : TStringList;
begin
Result :=False;
SL :=TStringList.Create;
Try
SaveToStringList(SL);
Try
  SL.SaveToFile(FileName);
Except
  Exit;
end;
Finally
SL.Free;
end;
Result :=True;
end;

function TRialIniFile.GetIdentValue(Const Section, Ident, DefaultValue : String) : String;
Var
   ptS : ptSection;
begin
ptS :=FindExistsSection(Section);
If (ptS <> Nil)then begin
Result :=ptS^.Idents.Values[Ident];
If (Result = VoidName)then
  Result :=DefaultValue;
end else
Result :=DefaultValue;
end;

procedure TRialIniFile.SetDelim(Const Delim : Char);
Var
   I : Integer;
begin
FDelim :=Delim;
For I :=0 to FSections.Count - 1 do
ptSection(FSections.Items[I])^.Idents.Delimiter :=Delim;
end;

procedure TRialIniFile.LoadFromStringList(Const StringList : TStringList);
Var
   I                : Integer;
   Len              : Integer;
   Line             : String;
   ptCurrentSection : ptSection;
begin
ptCurrentSection :=FindSection(VoidName);  //В начале возможен комментарий
For I :=0 to StringList.Count - 1 do begin
Line :=StringList.Strings[I];
Len  :=Length(Line);
If (Len>0)then
  If (Line[1] = FLeftSym)and(Line[Len] = FRightSym)then ptCurrentSection :=FindSection(Copy(Line, 2, Len - 2))
                                                   else ptCurrentSection.Idents.Add(Line);
end;
end;

function TRialIniFile.LoadFromFile(Const FileName : String) : Boolean;
Var
   SL : TStringList;
begin
Result :=False;
If (FileExists(FileName))then begin
SL :=TStringList.Create;
Try
  Try
   SL.LoadFromFile(FileName);
  Except
   Exit;
  end;
  LoadFromStringList(SL);
Finally
  SL.Free;
end;
Result :=True;
end;
end;

function TRialIniFile.ReadSection(Const SectionName : String; Const StringList : TStringList) : Boolean;
Var
   ptS : ptSection;
begin
ptS :=FindExistsSection(SectionName);
If (ptS <> Nil)then begin
StringList.Assign(ptS^.Idents);
Result :=True;
end else
Result :=False;
end;

procedure TRialIniFile.WriteSection(Const SectionName : String; Const StringList : TStringList);
Var
   ptS : ptSection;
   I   : Integer;
begin
ptS :=FindSection(SectionName);
For I :=0 to StringList.Count - 1 do
ptS^.Idents.Add(StringList.Strings[I]);
end;

procedure TRialIniFile.WriteString(Const Section, Ident : String; Const Value : String);
begin
AddIdentValue(Section, Ident, Value);
end;

procedure TRialIniFile.WriteInteger(Const Section, Ident : String; Const Value : Int64);
begin
AddIdentValue(Section, Ident, IntToStr(Value));
end;

procedure TRialIniFile.WriteFloat(Const Section, Ident : String; Const Value : Extended);
begin
AddIdentValue(Section, Ident, FloatToStr(Value));
end;

procedure TRialIniFile.WriteBool(Const Section, Ident : String; Const Value : Boolean);
begin
AddIdentValue(Section, Ident, BoolToStr(Value));
end;

function TRialIniFile.ReadString(Const Section, Ident : String; Const Default : String) : String;
begin
Result :=GetIdentValue(Section, Ident, Default);
end;

function TRialIniFile.ReadInteger(Const Section, Ident : String; Const Default : Int64) : Int64;
begin
Result :=StrToInt64(GetIdentValue(Section, Ident, IntToStr(Default)));
end;

function TRialIniFile.ReadFloat(Const Section, Ident : String; Const Default : Extended) : Extended;
begin
Result :=StrToFloat(GetIdentValue(Section, Ident, FloatToStr(Default)));
end;

function TRialIniFile.ReadBool(Const Section, Ident : String; Const Default : Boolean) : Boolean;
begin
Result :=StrToBool(GetIdentValue(Section, Ident, BoolToStr(Default)));
end;

function TRialIniFile.FindIdent(Const PrevSection, Ident : String; Out Section, Value : String) : Boolean;
Var
   ptS : ptSection;
   I   : Integer;
   P   : Integer;
   S   : String;
begin
ptS :=FindExistsSection(PrevSection);
If (ptS = Nil)then P :=0
              else P :=FSections.IndexOf(ptS) + 1;
Result :=False;
For I:=P to FSections.Count - 1 do begin
ptS :=FSections.Items[I];
S   :=ptS^.Idents.Values[Ident];
If (S <> VoidName)then begin
  Section :=ptS^.Name;
  Value   :=S;
  Result  :=True;
  Exit;
end;
end;
end;

function TRialIniFile.GetSectionsCount : Integer;
begin
Result :=FSections.Count;
end;

function TRialIniFile.GetSections(Const Index : Integer) : TStringList;
begin
Result :=ptSection(FSections.Items[Index])^.Idents;
end;

procedure TRialIniFile.SetSectionName(Const Index : Integer; Const SectionName : String);
begin
With ptSection(FSections.Items[Index])^ do begin
Name  :=SectionName;
HName :=UpperCase(SectionName);
end;
end;
function TRialIniFile.GetSectionName(Const Index : Integer) : String;
begin
With ptSection(FSections.Items[Index])^ do begin
Result  :=Name;
//HName :=UpperCase(SectionName);
end;
end;

function TRialIniFile.IndexOfSection(Const SectionName : String) : Integer;
Var
   ptS : ptSection;
begin
ptS :=FindExistsSection(SectionName);
If (ptS = Nil)then Result :=VoidInt
              else Result :=FSections.IndexOf(ptS) + 1;
end;

end.

(*
{
Поиск идентификатора:
Var
    sSec    : String;
    sOldSec : String;
    sVal    : String;
...
sldSec :="";
sVal    :="";
While(FindIdent(sOldSec, "Имя поля", sSec, sVal))do begin
ShowMessage(sVal);
sOldsec    :=sSec;
end;

Версия 2.2.0
}


*)

Alex2013
долгожитель
 
Сообщения: 2957
Зарегистрирован: 03.04.2013 11:59:44

Re: Подразделы (SubSections) в INI-файле

Сообщение RRYTY » 17.09.2023 13:31:30

Alex2013 писал(а): ... если задача укладывается в рамки простого и главное в принципе редактируемого в ручном режиме INI-файла то "нафига козе боян"? ...


Редактируемый в ручном режиме ini-файл - это текстовый файл.

Alex2013 писал(а): ... В общем народ, кто-нибудь сталкивался с готовым решением для работы с SubSections INI-файлов в Lazarus/fpc? ...


Никто никогда не будет вам писать то, что вам нужно. Ваш файл нужен только вам.

Alex2013 писал(а): ... (ничего сложного в этом нет, но очень не хочется "изобретать велосипед" )


Работа с текстовым файлом уже изобретена. В поисках готового решения вы и прикрутите кучу косяков в виде многоколесного драндулета (гвоздями прибъете свое творение к версии и виду ОС, версии компилятора, наличия вспомогательных системных, в том числе, библиотек), вместо простого и ясного, оптимизмрованного под вашу задачу, изящного решения. В поисках борьбы с чужими косяками нет ограничений. :)
RRYTY
постоялец
 
Сообщения: 187
Зарегистрирован: 25.12.2021 10:00:32

Re: Подразделы (SubSections) в INI-файле

Сообщение ssnakess » 17.09.2023 17:03:58

ИМХО, если нужна древовидная структура файла с настройками, то лучше и проще использовать или XML или JSON
Тем более что это уже все реализовано из коробки. И вы получите и кросплатформенность компиляции, и удобство для внутреннего использования.

Т.к. прикручивая подразделы к ini Вы заранее закладываете логику работы с ними, понятную только вам, и которую потом будет сложно объяснить потребителю.
Тогда как XML или JSON - понятны и описаны
ssnakess
новенький
 
Сообщения: 36
Зарегистрирован: 24.09.2011 23:08:55

Re: Подразделы (SubSections) в INI-файле

Сообщение stikriz11 » 17.09.2023 22:51:32

Alex2013 писал(а):Например зачем нужен ключ "ID={...}" и главное чем и как это читается создается и поддерживается .

Это кусок реального ини файла. Главное - это строка:
LIST_OF_CHILDRENS={1D4B1A84-2195-4A33-AF3F-0652F58E0EE1},{9F4D9467-6C6B-4320-A56B-499821A60082}
Т.е. список секций, которые являются ветками узла. Реализация простая. Каждый узел пишет себя в ини файл сам и вызывает метод записи у детей.
stikriz11
постоялец
 
Сообщения: 114
Зарегистрирован: 04.09.2023 15:54:19

Re: Подразделы (SubSections) в INI-файле

Сообщение Alex2013 » 19.09.2023 11:54:47

RRYTY писал(а):Работа с текстовым файлом уже изобретена. В поисках готового решения вы и прикрутите кучу косяков в виде многоколесного драндулета (гвоздями прибъете свое творение к версии и виду ОС, версии компилятора, наличия вспомогательных системных, в том числе, библиотек), вместо простого и ясного, оптимизмрованного под вашу задачу, изящного решения. В поисках борьбы с чужими косяками нет ограничений.

Я в курсе... ( Именно так я поступил при переименовании и "перестановке" секций - в первом случае просто отредактировал текст, во втором "пересобрал" INI в памяти, перечитав секции в нужном порядке )

Но увидев, что в дельфи есть метод ReadSubSections я подумал, что возможно где-то есть его готовый "самописный аналог" для лазарус.

Зы
Спасибо за отзывы и советы! Пока делаю через " переключение текущего ini-файла" (это точно надежнее всех прочих вариантов ) а дальше возможно сделаю "вложенные секции" замаскированные под комментарий. ( Идея проста: читаю "секцию подраздела" через ReadRawSection убираю комментарий и загружаю в TMemIniFile ( "наглядная бесконечная вложенность секций" прилагается автоматом )
Код: Выделить всё
[Секция1]
...
[Секция2]
...
[СубСекция1]
# [Секция1]
# ...
# [Секция2]
# ...
# [СубСекция 1_1 ]
# # [Секция1]
# # ...
# # [Секция2]
# #  ...

ИМХО такой формат будет наглядным и простым, хотя возможно будут некоторые сложности с навигацией ( особенно при возвращении на уровень выше ) но с другой стороны если открытие уровней всегда будет последовательным, то ничто не мешает сделать "классическую рекурсию" .
Alex2013
долгожитель
 
Сообщения: 2957
Зарегистрирован: 03.04.2013 11:59:44

Re: Подразделы (SubSections) в INI-файле

Сообщение v-t-l » 20.09.2023 12:37:29

Код: Выделить всё
ini.WriteString('Section1/SubSection0', 'IdentX', 'ValueX');
v-t-l
энтузиаст
 
Сообщения: 728
Зарегистрирован: 13.05.2007 16:27:22
Откуда: Belarus

Re: Подразделы (SubSections) в INI-файле

Сообщение Alex2013 » 20.09.2023 23:19:20

Сделал с "переключением ини-файла".
Изображение

Добавлено спустя 1 час 5 минут 14 секунд:
v-t-l писал(а):
Код: Выделить всё
ini.WriteString('Section1/SubSection0', 'IdentX', 'ValueX');

Это понятно но выйдет громоздко и почти "нечитаемо", а пожалуй единственное достоинство Ини-файлов именно в том что они поддерживают "ручной режим" правки и просмотра. :idea:
Alex2013
долгожитель
 
Сообщения: 2957
Зарегистрирован: 03.04.2013 11:59:44


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 112

Рейтинг@Mail.ru