On-line: гостей 0. Всего: 0 [подробнее..]
АвторСообщение





Пост N: 243
Зарегистрирован: 17.10.05
ссылка на сообщение  Отправлено: 19.12.24 17:39. Заголовок: hbini.prg


Покрутил, потестировал функцию hb_iniRead для работы с ini-файлами.

Хочу поделиться мыслями:
В память закачивается дерево хэш массивов.
Комментарии ';' и '#' игнорируются.
Вообще все строки, где нет разделителя "=" - идут в игнор.
И если затем записать файл с помощью hb_iniWrite - то в файле будут только
секции со строками key = valiue

Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 15 [только новые]


постоянный участник




Пост N: 4660
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 19.12.24 18:47. Заголовок: krutoff пишет Покрут..


krutoff пишет
 цитата:
Покрутил, потестировал функцию hb_iniRead для работы с ini-файлами


посмотрите в MiniGui h_objects.prg (исп. этой ф-ии)
...
CLASS TIniData INHERIT THmgData
...
и примеры со строками
 
oIni := TIniData():New(cIni, .T.):Read()
...
//oIni := TIniData():New(cIni, .T.):Read() - значения для ключей будут форматированы по типам
//oIni := TIniData():New(cIni, .F.):Read() - значения для ключей будут только типа "C"
//oIni := oIniData( cFileDcrp, .T., lUtf8, ):Read() - это читать из файла
//oIni -> это hash с вложенными hash секциями и вложенными в них hash ключами

// считать настройку cnfg-файл в переменную oCnf из переменной cBuff
oCnf := TIniData():New( , .T., lUtf8, , cBuff ):Read()
...
и т.д.


Спасибо: 1 
ПрофильЦитата Ответить





Пост N: 244
Зарегистрирован: 17.10.05
ссылка на сообщение  Отправлено: 20.12.24 16:44. Заголовок: Спасибо за ответ, Се..


Спасибо за ответ, Сергей!
Воспользовался Вашим советом. Получилось вот что.
Сразу скажу, что мне бывает необходимо закинуть просто текст в секцию с маркерами для подстановки значений.
Раньше это делал с помощью _getPrivateProfileSection(). Тут такого нет.
Кстати hb_iniRead обрабатывает фразу include и вставляет секции из include-файла.

Ну вот. Есть файл Test1.ini:
Скрытый текст


Выполняю 2 строки
oIni := TIniData():New('Test1.ini', .F.):Read()
oIni:Write('Test2.ini')

Результат Test2.ini:
Скрытый текст


Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 4661
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 20.12.24 17:58. Заголовок: krutoff пишет мне бы..


krutoff пишет
 цитата:
мне бывает необходимо закинуть просто текст в секцию с маркерами для подстановки значений.


С TIniData не важно, есть ini или нет (ключи в секциях есть или нет), вы всегда можете работать с переменными oIni объекта (по мне, доступ к переменным в объекте-контейнере oIni удобнее, чем в hash). В примере Advanced\App_OopTemplate есть файлы ini, cfg, Андрей написал даже info комментарии в них и в prg, смотрите. Хранить в TIniData можно данные по типам C,N,L,D,A,B и даже данные объекта THmgData (ф-я o := oHmgData(), ...) как json данные, т.е. это несколько больше, чем просто файл ini. Создается, проверяется все оч. просто, примерно так
 
App.Cargo := oHmgData() ; o := App.Cargo
...
o:lIni := hb_FileExists(cIni)
// доступ к ини-файлу везде в программе - App.Cargo:oIni
o:oIni := TIniData():New(cIni, .T.):Read()

Default o:oIni:INFO := oHmgData() // <- secija, если ее нет в переменной (ini), будет создана, как и переменные ниже
Default o:oIni:INFO:Developed_in := MiniGUIVersion()
Default o:oIni:INFO:xBase_compiler := Version()
Default o:oIni:INFO:C_compiler := Hb_Compiler()
Default o:oIni:INFO:Programm := o:cTitle
Default o:oIni:INFO:ProgVers := o:cVersion
Default o:oIni:INFO:Avtor := o:cAvtor
Default o:oIni:INFO:Email := o:cEmail

Default o:oIni:MAIN := oHmgData() // <- secija
Default o:oIni:MAIN:ExeFile := App.Exename
Default o:oIni:MAIN:aBClrMain := {215, 166, 0}
Default o:oIni:MAIN:ComSanMS := { o:cFontName2 , o:nFontSize+2 , .F., .F. } // фонт главного верхнего меню
Default o:oIni:MAIN:aWindow := {0, 0, 0, 0}
// TsBrowse
Default o:oIni:TsBrowse := oHmgData() // <- secija
Default o:oIni:TsBrowse:Normal := { o:cFontName, o:nFontSize , .F., .F. }
Default o:oIni:TsBrowse:Bold := { o:cFontName, o:nFontSize , .T., .F. }
Default o:oIni:TsBrowse:Italic := { o:cFontName, o:nFontSize-2, .F., .T. }
Default o:oIni:TsBrowse:ItalBold := { o:cFontName, o:nFontSize-2, .T., .T. }
Default o:oIni:TsBrowse:SpecHdr := { o:cFontName, o:nFontSize-2, .T., .T. }
Default o:oIni:TsBrowse:SuperHdr := { o:cFontName, o:nFontSize-2, .T., .F. }
Default o:oIni:TsBrowse:Edit := { o:cFontName, o:nFontSize+2, .F., .F. }
//_o2log(o:oIni, 27, ProcNL() + " o:oIni => ", .T. ) ; ?

Default o:oIni:WinDebug := oHmgData()
Default o:oIni:WinDebug:Rem := "Координаты окна отладки"
Default o:oIni:WinDebug:nY := 0
Default o:oIni:WinDebug:nX := 0

IF !o:lIni
// если нет файла, то создадим его
o:oIni:cCommentBegin := " Modify: " + hb_TtoC( hb_DateTime() )
o:oIni:Write() // НЕ UTF8, т.е. нет BOM на выходе
ENDIF
...


 цитата:
Кстати hb_iniRead обрабатывает фразу include и вставляет секции из include-файла.


Этим не пользовался, т.к. в объекте-контейнере есть свои варианты слияния нескольких переменных oIni в один, добавление в него hash, array, json данных -> в основе лежит класс THmgData, смотрите его методы и свойства
PS.
тут https://clipper.borda.ru/?1-4-0-00001425-000-0-0-1729596515 пример использования oHmgData() для разных вычислений (по адресу счетчик) в примере App_OopReport подсчет итогов, т.е. секция это вариант oHmgData() контейнера со всеми вытекающими

Спасибо: 1 
ПрофильЦитата Ответить





Пост N: 245
Зарегистрирован: 17.10.05
ссылка на сообщение  Отправлено: 21.12.24 12:48. Заголовок: Сергей, спасибо за о..


Сергей, спасибо за ответ!
Ваш TiniData очень хорош, мне все тут подходит, если бы не одно но:
(правда, это не критично, можно попробовать обойтись и без комментов)

Метод TIniData():New(cIni, .T.):Read() использует функцию hb_iniReadStr(),
которая глотает комментарии ';' и '#' и на выходе выдает дерево HASH-массивов.
Вообще все строки, где нет разделителя "=" - идут в игнор.

В Вашем примере Advanced\App_OopTemplate в файле Demo_timer.ini в самом начале файла я поставил:

;COMMENT1
;COMMENT2
#COMMENT 3

[HELP]
Тут должна быть информация #HELP

[TEST]
01 = TEST #COMMENT 4
#COMMENT 5

Запустил Demo_timer.exe и сразу закрыл.
Начало файла Demo_timer.ini стало таким:

#COMMENT 3

[HELP]

[TEST]
01 = TEST

P.S. Пример использования oHmgData() с hb_memoread(cFileini) очень заинтересовал -
применить его вместо hb_iniReadStr, а парсинг hb_iniStringLow() доработать.

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 4662
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 21.12.24 13:59. Заголовок: krutoff пишет Метод ..


krutoff пишет
 цитата:
Метод TIniData():New(cIni, .T.):Read() использует функцию hb_iniReadStr(),
которая глотает комментарии ';' и '#'


Как говорится "Не виноватая я, он сам ... ", так работает эта ф-я в hb + она воспринимает "[" в любом месте, как начало новой секции, т.к. в работе часто после = надо ссылаться на секцию, для настройки, то в примерах и для json вместо "[","]" используются скобки "<",">", для ";" есть переменная объекта VAR cCommentChar AS STRING INIT ";", которую можно сменить параметром
TIniData():New( cIni, lMacro, lUtf8, cChar, cData, cSrcChar, cOutChar )
выделенное синим, позволяет на лету делать подмену символа при чтении строки (METHOD ToValue( cStr )), т.е.
 
IF !Empty( ::cSrcReplChar )
cStr := StrTran( cStr, ::cSrcReplChar, ::cOutReplChar )
ENDIF


 цитата:
Запустил Demo_timer.exe и сразу закрыл.
Начало файла Demo_timer.ini стало таким:


Особенность работы с TIniData еще в том, что (по мне) ini, cfg файлы надо набирать руками, как настроечные, тогда коменты в строках "; ..." с "=" будут сохранены (с "#" остается как было, так работают ф-ии). Если создать ini, cfg программно и потом внести коменты, то эти файлы можно класть в ресурсы, как базовые настройки, менять некоторые настройки в них (привязка к клиенту) можно из обычных файлов ini, cfg у конкретного клиента, сделав чтение и слияние с данными oIni из ресурсов. Еще всегда есть возможность обработки файла своими средствами, прочитав в буффер cBuff := hb_memoRead(cFile), обработать как вам надо, ... и потом формировать секции и ключи для работы в переменной oCnf := TIniData():New( , .T., lUtf8, , cBuff ):Read()
Для программного формирования файлов с комментами, надо для символов комментариев использовать другие данные, отличные от тех, которые исп. родные ф-ии hb при чтении файлов, если это надо
PS.
запись в ini
[HELP]
Тут должна быть информация #HELP
всегда можно заменить на
[HELP]
Rem = Тут должна быть информация ;HELP
или
[HELP]
Help1 = Тут должна быть информация
Help2 = ...
...
или
[HELP]
Help = {"Тут должна быть информация", "#HELP", ...} ; тут текст коммента

Спасибо: 1 
ПрофильЦитата Ответить





Пост N: 246
Зарегистрирован: 17.10.05
ссылка на сообщение  Отправлено: 21.12.24 14:29. Заголовок: Сергей, спасибо за д..


Сергей, спасибо за детальное пояснение!
Стратегия работы с ini-файлами у меня практически такая же.
Попробую все перевести на TiniData. Тут возможностей больше.
Спасибо!

Спасибо: 0 
ПрофильЦитата Ответить





Пост N: 247
Зарегистрирован: 17.10.05
ссылка на сообщение  Отправлено: 21.12.24 14:36. Заголовок: P.S.


А нельзя в методе Read( cIniNew ) CLASS TIniData переопределить символ '#'
У меня в ini есть куча строк типа #WIDTH =550;550
К примеру #WIDTH использую как ключевое слово, а не параметр.

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 4663
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 21.12.24 15:40. Заголовок: krutoff Для информа..


krutoff
Для информации, вариант исп. в oHmgData() контейнере псевдо методов (блоки кода) и выполнение их методом :Do(...)
Это кусочек кода из примера "Testing DEMO Odbc/Firebird" (в hmg его нет)Скрытый текст

для более полного понимания исп. объекта-контейнера
Использование Скрытый текст


Спасибо: 1 
ПрофильЦитата Ответить





Пост N: 248
Зарегистрирован: 17.10.05
ссылка на сообщение  Отправлено: 21.12.24 15:48. Заголовок: Спасибо большое! Буд..


Спасибо большое! Буду разбираться.

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 4664
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 21.12.24 16:17. Заголовок: krutoff пишет А нель..


krutoff пишет
 цитата:
А нельзя в методе Read( cIniNew ) CLASS TIniData переопределить символ '#'


"#" если правильно помню, так комменты, отрабатывают в hb функциях.
Отдельно читаю файл от начала и с конца, для получения данных в переменных :cCommentBegin, :cCommentEnd и сам "#" не отрабатываю
у себя ключи иногда делаю с "_", ваш вариант ~ так сделать
_WIDTH =550,550
еще часто ключи делаю
001 = /spacetv.
002 = /ott.
003 = /ott-
004 = /myott.
005 = /mytv.
006 = /tvmedia2.
007 = /hlss.goodgame.
008 = /cdn1.
009 = /cdn01.
010 = /variant.m3u8
011 = /dmitry-
012 = /zabava-
013 = /okkotv-
014 = /cloud06.
015 = /viacomitalytest-
016 = /autopilot.
017 = /sc.
...
PS.
Если сейчас значение по ключу получаете через ф-ю, то можно сделать подмену (в ini иметь _Width = ...), а в ф-ии
...
IF left(cKey, 1) == "#" ; cKey := "_"+subs(cKey, 2) // или простой ключ иметь cKey := subs(cKey, 2) в ini
ENDIF
Return App.Cargo:oIni:Get(cKey, xDef)

Спасибо: 1 
ПрофильЦитата Ответить
постоянный участник




Пост N: 4665
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 22.12.24 21:38. Заголовок: krutoff Собрал прим..


krutoff
Собрал пример (выше код был кусочек) с посл. версией hmg, смотрите (кому интересно)
Тут (вместе с Firebird) https://TransFiles.ru/ki7ys
ставлю firebird C:\Firebird_2_5
запуск сервера с иконки
Target: C:\Firebird_2_5\bin\fbguard.exe -a
Start in: C:\Firebird_2_5\bin
пример в Advanced\_FDB_odbc
demo_run.bat запускает demo.exe на несколько fdb

Спасибо: 1 
ПрофильЦитата Ответить





Пост N: 249
Зарегистрирован: 17.10.05
ссылка на сообщение  Отправлено: 29.12.24 14:08. Заголовок: Добрый день! Сделал..


Добрый день! Сделал альтернативный упрощенный вариант TiniData "для себя".
Сергей, если Вам будет интересно, то, мне кажется, METHOD Read и Write
можно скомбинировать с этим кодом.
Да, я для себя VAR cNote2 ставлю '~'

Я в ini-файле формирую структуру, названия, Tooltip для полей файла.
И тут же ставлю ключи для формирования экранных и печатных форм для файла.
Так сложилось, что у меня там есть одинаковые ключевые слова
#LABEL, #BUTTON, #TABLE, #TABLA, #RTF и т.п.

Пример:
Скрытый текст


Поэтому сделал такой вариант TiniData. Он решает мои проблемы:
Скрытый текст


Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 4666
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 29.12.24 16:28. Заголовок: krutoff пишет Сделал..


krutoff пишет
 цитата:
Сделал альтернативный упрощенный вариант TiniData "для себя".


Вы совершенно правы THmgData можно обвешивать разным синтаксисом для работы, например, для окон сделать ф-ю
Скрытый текст

немного поправить h_window.prg Скрытый текст

и ваши окна будут работать от данных ini\cfg файлов, созданных и прочитанных в THmgData контейнер
Контролы можно так же ввести в такую схему работы

Спасибо: 1 
ПрофильЦитата Ответить





Пост N: 250
Зарегистрирован: 17.10.05
ссылка на сообщение  Отправлено: 30.12.24 16:07. Заголовок: В методе METHOD Read..


В методе METHOD Read я соединил функции hb_iniReadStr, hb_iniFileLow и hb_iniStringLow.
В блоке hb_iniStringLow добавил доп. обработку и вставку комментов и строк без разделителя.
METHOD Write тоже обрабатывает все ваши переменные a_a_Key класа THmgData без
переходных hash-переменных.
Так, что если заинтересует, предлагаю применить.
В последней версии блок проверки на ReadOnly файл переставил в METHOD Write.

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 4667
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 30.12.24 17:59. Заголовок: krutoff пишет Так, ч..


krutoff пишет
 цитата:
Так, что если заинтересует, предлагаю применить


Это скорее к Григорию. Со времен clipper в ini файлах использовал в стандарте # и ; как комментарии, даже :Write() не использовал - хватало. Ключ, начинающийся с #KeyName, использовал в VO, отказался быстро, т.к. исп. его, ключ, как имена переменных (правила). То что есть мне хватает выше головы, причем, файлы ini\cfg у меня всегда в Utf8, для других данных сохранение может быть в json (htm, xml, js) или hb_valtoexp(...) и могут быть подчитаны при чтении ini\cfg блоком кода или ф-ей типа (в ini\cfg) xVal1 := {|| myRead(".\wrk\имя файла") }

Спасибо: 1 
ПрофильЦитата Ответить
Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 159
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет