Что нового

Ограничение по работе с ini файлами

AZJIO

Меценат
Меценат
Сообщения
2,879
Репутация
1,194
gregaz
Я обновил опять, в предыдущем варианте объявление массива было испорчено из-за переноса локальных в начало списка. Функцию удаления сделал отдельно внутреннюю.

Не понял про _IniVirtual_DeleteEx. На словах можно? При уделении ячейки нам надо сдвинуть остальные на место удалённого, в общем все после найденного индекса сдвинуть к началу и этот процес нельзя ускорить никак, кроме как взять последнюю ячейку и вставить на место удалённой и уменьшить размер на 1.
 

AZJIO

Меценат
Меценат
Сообщения
2,879
Репутация
1,194
gregaz
Надо улучшать регулярное выражение, если секции пустые и без лишних переносов строк, то не захватывает секции через одну.
И ещё странный глюк: пример в IniReadSectionNames с использованием win.ini захватывает текст которого не в реальном win.ini, как будто совсем другой файл, в то время как _IniVirtual_Initial с тем же путём возвращает реальный файл. Это я уже примеры демонстрационные хотел сделать, видимо рано.

В принципе разобраться с правилами ini. Например выяснилось что [ и ; не могут быть в параметрах, хотя можно было бы предположить что это правило распостроняется только при квадратных скобках с обоих сторон, а нет уже с одной стороны достаточно чтобы не считать его параметром.


Добавлено:
Сообщение автоматически объединено:

Добавил поддержку пробельных символов по краям параметров, время сохранения в 3 раза возросло. Потому что при сохранении регулярное выражение проверяет для каждого параметра.


Добавлено:
Сообщение автоматически объединено:

IniVirtual.7z новая версия с примерами, исправлен _IniVirtual_WriteSection
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
AZJIO,
Навскидку, вроде все нормально.
Теперь RenameSection работает быстрее . А замедлений нигде особенно не почувствовал. Сравнивал с предыдущей версией.
Надо глубже потестить
Кстати в процессе работы Ини-файл переформатируется с пустыми строками между разделами .
Может есть смысл добавить возможность непереформатирования ? А может добавить ф-ию удаления пустых строк?

Маленькая описка в примере к ф-ии : _IniVirtual_ReadSection
_ArrayDisplay($aRes, 'Имена секций')


Добавлено:
Сообщение автоматически объединено:

P.S.
Может добавить сервисную ф-ию сравнения исходного текста с текстом после работы ф-ии : _IniVirtual_Save
на предмет определения изменилось ли основное тело файла.
Это имеет смысл для выполнения уже записи в файл (с заменой или в конец файла)
 

AZJIO

Меценат
Меценат
Сообщения
2,879
Репутация
1,194
gregaz
Да пустые секции добавляется лишний перенос, можно сделать чтобы если секция пуста то не добавлять перенос строки, но влюбом случае результат будет согласно формату, а не то чтобы проверять форматирование текущего ini-файла и подстраиваться под него. Там ещё вокруг "=" тоже пробелы исчезают, даже если они были. Разделы слитно хуже читаются, перед новым разделом с данными должна быть пустая строка, мне кажется так проще видно начало нового раздела.

Были такие мысли: добавить новый параметр в конец функций переименования и удаления. Теоритически позиция разделов и параметров не имеет значения, поэтому тем кому важна скорость не имеет смысла сдвигать все 1000 ключей при удалении первого.
Ещё была мысль: добавить ключ, который бы указывал изменение параметров и наличие пробела с краёв. Например в массиве рядом с ячейкой счётчика пустует и там можно хранить не форматированные данные (секция текстом как есть) или в 4-ой колонке основного 2D-массива, а третья колонка 2D-массива содержит ключ изменений 0 или 1. Если происходит запись в секцию, то функция записи устанавливает ключ с 0 в 1. То есть когда сохраняем, то записываем секции с ключам 0 как есть из ячейки, где полный текст. Это увеличит занимаемую память на размер копии ini-файла, но и скорость функции сохранения увеличится.


Добавлено:
Сообщение автоматически объединено:

gregaz
Это имеет смысл для выполнения уже записи в файл (с заменой или в конец файла)
В конец файла ни как не получится, только замена всего. Там же старые данные, как можно в конец дописывать ещё теже секции? Будут просто куча дубликатов.



Добавлено:
Сообщение автоматически объединено:

Чтобы удалить изменённые секции придётся читать файл и записывать полностью, так что всё равно будет тоже самое.
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
Я имел в виду ф-ию , которая выявит совпадение основного тела и если не изменилось ,
то выдаст фрагмент конца текста для записи.
Ну вобщем это нереально, поскольку текст даже не изменяясь -все же форматируется.
Вопрос снимается.
 

AZJIO

Меценат
Меценат
Сообщения
2,879
Репутация
1,194
gregaz
Перезалил, сделана поправка для исключения закомментированных параметров.


Добавлено:
Сообщение автоматически объединено:

gregaz
IniVirtualSPE Вот ещё потестируй вариант на парсинге регулярными выражениями, аналогично IniString, только нет проблем с метасимволами в именах и значения возвращает без кавычек.

IniVirtual пока не является законченным вариантом, нужно добавить всё-таки проверку входных параметров.
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
AZJIO

Пока навскидку.
IniVirtualSPE проигрывает в скорости IniVirtual
Особенно на больших файлах.
На моих нестандартных в разы.
Имеет некоторое преимущество только ф-ия IniVirtualSPE_Read и то только на очень коротких простых файлах

По сравнению с IniString быстее в разы
На длинных файлах даже больше , чем на порядок

Нашлось пара некорректностей :

1. Ф-ия _IniVirtualSPE_Read не корректно возвращает отсутствующий параметр
Код:
;Заменить :
	If @error Then Return SetError(1, 0, '')
	;на : 
	If @error Then Return SetError(1, 0, $sDefault)


2.Ф-ия _IniVirtual_ReadSection
При чтении пустой секции должна устанавливать @Error=1

На мой взгляд IniVirtualSPE_Read не представляет интереса, т.к. на файлах < 32 прекрасно будет работать нативные ф-ии .
IniVirtual прекрасно работает особенно на нестандартных длинных файлах
 

AZJIO

Меценат
Меценат
Сообщения
2,879
Репутация
1,194
gregaz
Нашлось пара некорректностей :
Думаю файл был скачан не сегодня, потому что с утра я уже выложил архивы IniVirtual и IniVirtualSPE с последними поправками и этих ошибок там нет. А также выложил CustomUDFs.chm с этими UDF. Думаю IniString убрать по проигрыванию в нескольких пунктах:
1. медленнее
2. не обраватывает кавычки для параметров с пробелом (хотя нативные тоже)
3. не работает с именами содержащими метасимволы рег. выр.
4. не находит параметры, если перед "=" пробельный символ.
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
В IniVirtual выявилось : (если нет хотя бы пробела в конце)
Код:
#include <IniVirtual.au3>
#include <Array.au3>

$s_Ini=@ScriptDir & "\Small.Ini"

$s_INI_Text="[AAA]" & @CRLF & _ 
			"Ivan=33" & @CRLF & _
			"Ann=25" & @CRLF & _
			"[BBB]" & @CRLF & _
			"[CC]"

$h_File=FileOpen($s_Ini, 2)		
FileWrite($h_File, $s_INI_Text)
FileClose($h_File)
$s_INI_Text=FileRead($s_Ini)

$a_Ini_Virtual2D=_IniVirtual_Initial($s_INI_Text)

MsgBox(4096, "$s_INI_Text", $s_INI_Text)
_ArrayDisplay($a_Ini_Virtual2D, "$a_Ini_Virtual2D")
; тогда, как :     
$aSect=IniReadSectionNames($s_Ini)
_ArrayDisplay($aSect, "$aSect")



Добавлено:
Сообщение автоматически объединено:

Это осталось :
Ф-ия _IniVirtual_ReadSection согласно работе нативной ф-ии
При чтении пустой секции должна устанавливать @Error=1

Ведь содержание секции не контролируется установленным : SetError(1, 0, 0)
Код:
IniReadSection($s_Ini, "BBB")
MsgBox(4096, "@error", @error);  @error =1
_IniVirtual_ReadSection($a_Ini_Virtual2D, "BBB")
MsgBox(4096, "@error", @error) ; @error=0
 

AZJIO

Меценат
Меценат
Сообщения
2,879
Репутация
1,194
gregaz
Обе ошибки исправил, перезалил IniVirtual.7z и IniVirtualSPE.7z
Сейчас есть отличие от нативных: при сохранении параметра с пробелами в начале и в конце данные автоматически заключаются в кавычки при сохранении. Я изменять в этом плане как у нативных не хочу, потому что это более походит баг.
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
Еще :
Код:
$sRead = _IniVirtual_Read($a_Ini_Virtual2D, "AAA", '=Ann', "Def");вернет значение
$sRead = _IniVirtualSPE_Read($s_ini_Text, "AAA", '=Ann', "Def") ;вернет значение

$sRead = IniRead($s_Ini, "AAA",  '=Ann', "Def")                ;вернет : "Def"



Добавлено:
Сообщение автоматически объединено:

и наоборот для :
Код:
$sKey=' Ann'
 

AZJIO

Меценат
Меценат
Сообщения
2,879
Репутация
1,194
gregaz
Полный пример можно?

Код:
#include <IniVirtualSPE.au3>
#include <IniVirtual.au3>

$s_INI_Text="[AAA]" & @CRLF & _ 
            "Ivan=33" & @CRLF & _
            "=Ann==Ann" & @CRLF & _
            "[BBB]" & @CRLF & _
            "[CC]"
$a_ini_Main2D = _IniVirtual_Initial($s_ini_Text)

$sRes1 = _IniVirtualSPE_Read($s_ini_Text, 'AAA', '=Ann', "Значение по умолчанию, если не найдено")
$sRes2 = _IniVirtual_Read($a_ini_Main2D, 'AAA', '=Ann', "Значение по умолчанию, если не найдено")
MsgBox(0, 'Сообщение', '|' & $sRes1 & '|' &@CRLF& '|' & $sRes2 & '|')


У меня возвращает нормально. Сейчас обновил оба архива указав версию (текущая 0.3, от последнего релиза на офсайте с учётом количества модификаций), чтобы не было путаницы и заменил "__GetKeysVal" на полное имя __IniVirtual_GetKeysVal и __IniVirtualSPE_GetKeysVal, чтобы не было конфликта с двумя версиями.
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
AZJIO [?]
Полный пример можно?
Код:
#include "IniVirtual.au3"
#include "IniVirtualSPE.au3"
$s_Ini=@ScriptDir & "\Small.Ini"


$s_INI_Text="[AAA]" & @CRLF & _ 
            "Ivan=33" & @CRLF & _
            "=Ann==Ann" & @CRLF & _
            "[BBB]" & @CRLF & _
            "[CC]"


$h_File=FileOpen(	$s_Ini, 2)		
FileWrite($h_File, $s_INI_Text)
FileClose($h_File)


$s_INI_Text=FileRead($s_Ini)
$a_ini_Main2D=_IniVirtual_Initial($s_INI_Text)

$sRes1 = _IniVirtualSPE_Read($s_ini_Text, "AAA", '=Ann',"Значение по умолчанию, если не найдено"); да
$sRes2 = _IniVirtual_Read($a_ini_Main2D, 'AAA', '=Ann', "Значение по умолчанию, если не найдено") ; да
$sRes3=IniRead($s_Ini, "AAA",  '=Ann', "Значение по умолчанию, если не найдено")                ; нет
MsgBox(0, 'Сообщение', '|' & $sRes1 & '|' &@CRLF& '|' & $sRes2 & '|'   &@CRLF& '|' & $sRes3 & '|')




Добавлено:
Сообщение автоматически объединено:

Кстати не пора ли выложить на своей ветке.
А то тема давно уже решена
Обсуждение не совсем потеме
Да и искать каждый раз где ссылка неудобно

Для
Код:
$sKey=' Ann'
; - на оборот : Нет - Нет - да
 

AZJIO

Меценат
Меценат
Сообщения
2,879
Репутация
1,194
gregaz
Кстати не пора ли выложить на своей ветке.
Выложил IniVirtual + IniVirtualSPE
Кстати параметр ' Ann' можно отнести к недостатку нативной функции, потому что ' Ann' и 'Ann' она считает одним и тем же параметром. Если что, на конференции AutoIt (jabber) можно было всё решить быстрее.
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
заметил, что функция
Код:
IniRenameSection

не работает, если в секции нет параметров (то есть она пустая)
странно, что в справке нет об этом упоминания.
в этом случае функция _IniString_RenameSection из IniString.au3 тоже не переименовывает секцию.
функция
Код:
_ReplaceStringInFile

дала нужный результат - секция переименована
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
joiner [?]
дала нужный результат - секция переименована
Я использую подобную функцию:

Код:
$iRet = _IniRenameSection('Test.ini', 'Old Sect', 'New Sect')

ConsoleWrite('$iRet: ' & $iRet & @CRLF & '@error: ' & @error)

Func _IniRenameSection($sIni_File, $sSection, $sNew_Section, $iFlag = 0)
	If $iFlag = 1 Then
		IniDelete($sIni_File, $sNew_Section)
	EndIf
	
	Local $sIni_Content = FileRead($sIni_File)
	
	If @error Then
		Return SetError(1, 0, 0)
	EndIf
	
	$sNew_Section = StringRegExpReplace($sNew_Section, '([][\^\\.+*?$(){}=!|:])', '\\\1')
	
	If $iFlag <> 1 And StringRegExp($sIni_Content, '(\r?\n|)\[' & $sNew_Section & '\](\r?\n|)') Then
		Return SetError(2, 0, 0)
	EndIf
	
	$sSection = StringRegExpReplace($sSection, '([][\^\\.+*?$(){}=!|:])', '\\\1')
	$sIni_Content = StringRegExpReplace($sIni_Content, '\[' & $sSection & '\]', '[' & $sNew_Section & ']')
	
	Local $hIni_Open = FileOpen($sIni_File, 2)
	FileWrite($hIni_Open, $sIni_Content)
	Return FileClose($hIni_Open)
EndFunc


Это аналог существующей, но без ограничения.
 
Сообщения
80
Репутация
-1
IniWrite пишет так как я ему и даю " -p pass", с пробелом в начале строки.
В процессе опытов он успешно писал в ini строку с несколькими пробелами в конце.

IniRead как оказалось не может читать пробелы по краям значений, он их обрезает по краям.
Есть какието решения ?

Хотел сделать универсальный параметр для данных типа
".d1" как дополнение к прошлому, или
" -m 32" как отдельный. Но видимо придётся делать отдельный слот, а пробелы напихивать между значениями.
Хорошо хоть консоли на них пофиг
 
A

Alofa

Гость
winix сказал(а):
... Есть какието решения ?..
Код:
$sPath_ini = @ScriptDir & '\Example.ini'
IniWrite($sPath_ini, 'Section', 'Key', '"           Значение             "')
$sRead = IniRead($sPath_ini, 'Section', 'Key', '')
MsgBox(4096, '', 'Значение параметра "Key" в секции "Section": [' & $sRead & ']')
FileDelete($sPath_ini)
 
Верх