Что нового

Баг в функции IniReadSectionNames()

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
Столкнулся с неожиданным ограничением в функции IniReadSectionNames(): ограничено общее количество символов в названиях всех секций INI-файла...
Пример с короткими названиями секций (будут выведены все 5000 названий секций):
Код:
; НАЧАЛО

 #Include <array.au3>
 $INI=@ScriptDir&'\test.ini'
 For $COUNTER=1 To 5000
  IniWrite($INI,$COUNTER,'par1','var1')
  IniWrite($INI,$COUNTER,'par2','var2')
  IniWrite($INI,$COUNTER,'par3','var3')
  IniWrite($INI,$COUNTER,'par4','var4')
  IniWrite($INI,$COUNTER,'par5','var5')
  IniWrite($INI,$COUNTER,'par6','var6')
 Next
 $A=IniReadSectionNames($INI)
 _ArrayDisplay($A)

; КОНЕЦ

Пример с длинными названиями секций (будут выведены 1365 названий секций):
Код:
; НАЧАЛО

 #Include <array.au3>
 $INI=@ScriptDir&'\test.ini'
 For $COUNTER=1 To 5000
  $MOMENT=@YEAR&'-'&@MON&'-'&@MDAY&'-'&@HOUR&'-'&@MIN&'-'&@SEC&'-'&@MSEC
  IniWrite($INI,$MOMENT,'par1','var1')
  IniWrite($INI,$MOMENT,'par2','var2')
  IniWrite($INI,$MOMENT,'par3','var3')
  IniWrite($INI,$MOMENT,'par4','var4')
  IniWrite($INI,$MOMENT,'par5','var5')
  IniWrite($INI,$MOMENT,'par6','var6')
 Next
 $A=IniReadSectionNames($INI)
 _ArrayDisplay($A)

; КОНЕЦ

Хотя в INI-файле будут созданы все 5000 секций в обоих примерах...
Как относиться к данному ограничению: как к багу?
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
snoitaleR [?]
Как относиться к данному ограничению: как к багу?
Ограничение (баг?) есть, только, к сожалению, о нем нет информации (или я ее не нашел). Попробуйте использовать библиотеки IniVirtual, IniVirtualSPE или IniString. Примеры есть в русской справке.
 
Автор
snoitaleR

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
madmasles
Я надеялся, что никогда не достигну технических ограничений в INI-файлах :smile: ...
Пока эту ошибку исправят (если исправят), пройдёт много времени...
Я выбираю в данный момент между переходом на базы данных (SQLite) и написанием самодельной функции IniReadSectionNames()...
Пока ещё не определился...
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
snoitaleR [?]
или написанием самодельной функции IniReadSectionNames()...
Можно, например, примерно так сделать.
Код:
#include <Array.au3>

$sINI = @ScriptDir & '\test.ini'
$aSectionNames = StringRegExp('[nothing]' & @CRLF & FileRead($sINI), '(?m)^\h*\[(.+)\]', 3)
$aSectionNames[0] = UBound($aSectionNames) - 1
_ArrayDisplay($aSectionNames)
PS
Не знаю, баг это или нет, но, если создать в ини-файле пустую секцию ([]), то штатная IniReadSectionNames возвращает пустую строку в массиве.
 
Автор
snoitaleR

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
madmasles
Спасибо... На данный момент это и есть решение проблемы... Все остальные INI-функции работают нормально...
Тему закрывать не буду, пока не узнаем официальный ответ от разработчиков...
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
madmasles [?]
Ограничение (баг?) есть, только, к сожалению, о нем нет информации
В справке написано:
Только первые 32767 символов раздела принимаются во внимания для совместимости с Win9x.
Хотя в реальности конечно это чуть меньше, по моим тестам, это 31399 символов (на общую длину имён секции).

snoitaleR [?]
Хотя в INI-файле будут созданы все 5000 секций в обоих примерах...
У меня кстати во втором примере не выводит все секции в файл...
Возможно связано со скоростью работы процессора, происходит две или более записей в одну миллисекунду :smile:.
 

CreatoR

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

Код:
Func _IniReadSectionNamesEx($sIniFile)
	Local $aFileReadArr = StringSplit(StringStripCR(FileRead($sIniFile)), @LF)
	If @error Then Return SetError(1, 0, "")
	
	Local $aRetArr[$aFileReadArr[0]+1], $iUbound, $iSplitPos, $sKey, $sValue
	
	For $i = 1 To $aFileReadArr[0]
		If StringRegExp($aFileReadArr[$i], '^\s*\[.+\]') Then
			$aRetArr[0] += 1
			$aRetArr[$aRetArr[0]] = StringRegExpReplace($aFileReadArr[$i], '^\s*\[(.+)\].*', '\1')
		EndIf
	Next
	
	ReDim $aRetArr[$aRetArr[0]+1]
	Return $aRetArr
EndFunc
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
CreatoR,
 

Вложения

  • sshot-5.png
    sshot-5.png
    27.4 КБ · Просмотры: 17

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
OffTopic:
Версия 3.3.10.0 уже даже W2k не поддерживает
•Changed: Removed Windows 2000 support. Minimum supported OS is now Windows XP RTM / Windows Server 2003.
А данная проблема и в ней присутствует. Забыли снять ограничение, что ли?
 

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
Верну ограничение. Изначально по именам даже не представлялось реальным иметь ограничение, только по размеру секции в основном были, там и оставлено. Видимо единица буфера для возврата любых данных связанных с ini установлен с ограничением. А тем более 32767 ни как не воспринимался с ограничением суммы имён, скорее к одному имени, а тут для суммы оказалось. И кстати формулировка на скрине не верна. Теперь можно более правильно указать - "Число возвращаемых имён ограничивается суммой длин всех имён не более 32767 символов.".


CreatoR [?]
Хотя в реальности конечно это чуть меньше, по моим тестам, это 31399 символов (на общую длину имён секции).
Попробовал разные длины имён, получилось ограничение зависит от количества секций (28080 - 31200), видимо разделитель для разделения имён учитывается как символ и при большем числе секций большее число разделителей и занимает большее места оставляя меньше на для секций.

snoitaleR
Ещё есть IniEx (DXRW4E)
 
Верх