Перейти к содержимому

Фотография

Ф-ции чтения из INI-файла и записи в INI-файл


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 7

#1 SergeyP

SergeyP

    Специалист

  • Members
  • PipPipPipPipPip
  • 651 сообщений
  • Город:Москва

Отправлено 21 мая 2010 - 10:24

Предлагаю функции чтения параметра из INI-файла и запись параметра в INI-файл с использованием KERNEL32

Ограничения : нет анализа на корректное имя и на существование INI-файла

Private dll_kernel32
Private lib_kernel32 
Private SZ_STR_LPSTR_DLL 
Private lp_NameFile 

' Иницализация для работы с KERNEL32 
Sub Init_KERNEL_32
 ' Defines the dll type
  Set dll_kernel32 = DLL.DefineDLL("KERNEL32")
 ' Loads the dll.
  Set lib_kernel32 = DLL.Load("KERNEL32")
  
  SZ_STR_LPSTR_DLL = 32768		' длина LPTSTR

  ' определение ф-ций работы с INI-файлами
  dll_kernel32.DefineProc "GetPrivateProfileStringA", vt_lpstr, vt_lpstr, vt_lpstr, vt_lpstr, vt_i4, vt_lpstr, vt_i4 
  dll_kernel32.DefineProc "WritePrivateProfileStringA", vt_lpstr, vt_lpstr, vt_lpstr, vt_lpstr, vt_i4 

End Sub

' Иницализация INI-файла 
Sub Init_INI (NameIniFile)
 
  Set lp_NameFile = DLL.New("LPSTR", SZ_STR_LPSTR_DLL)
  lp_NameFile.Text = NameIniFile 
  
End Sub


' Чтение параметра из INI-файла
'   Section	 - секция
'   Parameter   - параметр
'   val_Default - значение оп умолчанию (возвращается, если нет параметра)
' Возврат : значение параметра (если чтение успешное) или val_Default (если чтение безуспешное)   

Function  ReadIniFile (Section, Parameter, val_Default)
  Dim lp_Section, lp_Parameter, lp_Default, lp_ReturnedString, res 

  Set lp_Section = DLL.New("LPSTR", SZ_STR_LPSTR_DLL)
  lp_Section.Text = Section
 
  Set lp_Parameter = DLL.New("LPSTR", SZ_STR_LPSTR_DLL)
  lp_Parameter.Text = Parameter

  Set lp_Default  = DLL.New("LPSTR", SZ_STR_LPSTR_DLL)
  lp_Default.Text = val_Default 
	 
  Set lp_ReturnedString = DLL.New("LPSTR", SZ_STR_LPSTR_DLL)
  
  res = lib_kernel32.GetPrivateProfileStringA(lp_Section, lp_Parameter, lp_Default, lp_ReturnedString, SZ_STR_LPSTR_DLL, lp_NameFile)
  ReadIniFile = lp_ReturnedString.Text  
  
End Function

' Запись value в INI-файл
'   Section	 - секция
'   Parameter   - параметр
'   value - значение 

Sub WriteIniFile (Section, Parameter, value)
  Dim lp_Section, lp_Parameter, lp_value, res 

  Set lp_Section = DLL.New("LPSTR", SZ_STR_LPSTR_DLL)
  lp_Section.Text = Section
 
  Set lp_Parameter = DLL.New("LPSTR", SZ_STR_LPSTR_DLL)
  lp_Parameter.Text = Parameter

  Set lp_value  = DLL.New("LPSTR", SZ_STR_LPSTR_DLL)
  lp_value.Text = value 
	 
  res = lib_kernel32.WritePrivateProfileStringA(lp_Section, lp_Parameter, lp_value, lp_NameFile)
  
End sub

А вот пример использования функций

Sub CallRoutineFromDLL

  ' Иницация работы с DLL
  Init_KERNEL_32 

  Init_INI ("c:\a.ini")
  
  s_par = ReadIniFile ("q", "z", "ERROR")

  WriteIniFile "qq", "zz", "1234"

End sub

  • 0

#2 VitalyD

VitalyD

    Опытный участник

  • Members
  • PipPipPipPip
  • 285 сообщений
  • Город:Санкт-Петербург

Отправлено 21 мая 2010 - 11:31

Даже не знаю, что больший изврат, то что я предлагал (ниже), или это...

Код
function ReadINIFile(ini_file) {
	var INI = {};
	var FSO = new ActiveXObject("Scripting.FileSystemObject");
	if ((FSO.FileExists(ini_file)) && (FSO.GetFile(ini_file).Size > 0)) {
		with (FSO.OpenTextFile(ini_file)) {
			var text = ReadAll();
			Close();
			var arr_lines = text.split('\n');
			var section, param, value;
			for (var i in arr_lines){
				if (/^\[(\w+)\]/.test(arr_lines[i])){
					section = RegExp.$1;
					INI[section] = {};
				}
				if (/^([^;#][^=]*?)\s*=\s*([^\r\n]*?)\s*$/.test(arr_lines[i])){
					param = RegExp.$1;
					value = RegExp.$2;
					INI[section][param] = value;
				}
			}
		}
		return INI;
	}
}

С использованием данной функции получаем удобный объект для доступа к настройкам.
Например можно делать так:

Код
var settings = ReadINIFile("C:\\mySettings.ini");
var Param1 = settings.SectionName.ParamName

  • 0

#3 SergeyP

SergeyP

    Специалист

  • Members
  • PipPipPipPipPip
  • 651 сообщений
  • Город:Москва

Отправлено 21 мая 2010 - 11:50

VitalyD !

Вы предложили только функцию чтения параметра из INI-файла.
При этом, в ней не обрабатывается ситуация, когда параметра нет.

У Вас нет функции записи в INI-файл.

Кроме этого, смущает "var text = ReadAll()" : как работает Ваша функция на больших INI-файлах ? (несколько Mb)


Мои функции выполнены по аналогии с функциями из Delphi-библиотеки (IniFiles).
ИМХО, это правильно, иначе Borland (или как она сейчас называется ?) использовала бы построчную обработку файла.

А самое главное, мои функции для VB.
  • 0

#4 VitalyD

VitalyD

    Опытный участник

  • Members
  • PipPipPipPip
  • 285 сообщений
  • Город:Санкт-Петербург

Отправлено 21 мая 2010 - 12:01

Что значит не обрабатывается ситуация, когда параметра нет?)

Соль приведенного мною примера в том что на выходе функции вы получаете объект, который содержит все секции INI-файла в качестве свойст этого объкта. Сами же секции в качестве свойств содержат параметры. (То есть доступ к секциям и значеям осуществляется через точку: INIObject.SectionName.ParamName).
Соответсвенно фраза "не обрабатьывается ситуация когда парамметры нет" не имеет никакого смысла в данном случае...


ReadAll как раз и используется для того , что бы зачитать весь INI и конвертировать его в описанный объект, которым и пользоваться в дальнейшем не возвращаясь к самому INI-файлу...

А вообще я и не пытался меряться письками обсуждать что лучше или хуже :)
INI вообще ацтой :)
  • 0

#5 Genka

Genka

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 328 сообщений
  • ФИО:Геннадий Алпаев
  • Город:Украина, Днепр


Отправлено 21 мая 2010 - 18:37

Кроме этого, смущает "var text = ReadAll()" : как работает Ваша функция на больших INI-файлах ? (несколько Mb)


Я как-то проверял ReadAll с файлом размером 5 мегабайт - считался за пару секунд, так что с этим все ок
  • 0

TestComplete для начинающих (видеозаписи курса)

Software Testing Automation Tips (50 вещей, которые должен знать каждый автоматизатор, книга на английском языке)

Онлайн-учебник "Автоматизация тестирования от «А» до «Ы»"
Сборник рецептов по TestComplete (книга на английском языке)
Онлайн-учебник по TestComplete
Онлайн-учебник по SilkTest


#6 TC_Noob

TC_Noob

    Новый участник

  • Members
  • Pip
  • 45 сообщений

Отправлено 05 июня 2010 - 05:24

Естественно, наличие параметра необходимо проверять или мы живём в идеальном мире?

У Сергея приведена работа только с DLL и только c DLL, тем более c системными от M$, там уже до нас всё оптимизировали. В общем, зачёт :)
А что будет с конструкцией var text = ReadAll(), если у меня INI в 25 мегов?

А в другом примере, хосподи, с начала, activeX, потом парсинг :help: Удобно ли на кухню через окно с улицы заходить, когда живёшь на 10 этаже ?

А над этим я посмеялся

if ((FSO.FileExists(ini_file)) && (FSO.GetFile(ini_file).Size > 0)) {
with (FSO.OpenTextFile(ini_file)) {

Работа с текстовым файлом в TestComplete ДАВНО реализована и в Delphi с INI работают тоже через KERNEL32.dll, а мы всё велики конструируем, да? :help:
  • 0

#7 ЮстусТретий

ЮстусТретий

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

  • Members
  • PipPipPip
  • 201 сообщений
  • ФИО:Сергей

Отправлено 11 июня 2010 - 14:41

Хм... вообще в TC есть встроеный объект для работы с Ini файлами.

Из TC help'а:

Storages.INI(FileName) - Opens the specified INI file and returns the FileSection object for its root section

Parameters:
Storages The Storages object
FileName [in] Required String
Result A FileSection object

работает примерно так:

procedure Main;
var Value;
begin
v := Storages.INI('C:\test.ini');
Value := Storages.INI('C:\test.ini').GetSubSection('Section').GetOption('OptionName', 'not found');
Log.Message(Value); // выводится 100
end;


test.ini
[Root] <- обязательно должна быть !

[Section]
OptionName=100 <- пробела перед "=" не должно быть или имя опции в GetOption нужно указывать с пробелом
  • 0

#8 SergeyP

SergeyP

    Специалист

  • Members
  • PipPipPipPipPip
  • 651 сообщений
  • Город:Москва

Отправлено 18 июня 2010 - 04:52

Хм... вообще в TC есть встроеный объект для работы с Ini файлами.
....


ИМХО, этот объект годится для работы с пользовательскими INI-файлами.

А как работать, например, с системными INI-файлами (C:\WINDOWS\system.ini) ?
Конечно, можно, скопировать его (например в %temp% каталог), добавить в копию в начало строку [ROOT], а потом читать..

Что-то не очень мне это нравится..
  • 0


Количество пользователей, читающих эту тему: 1

0 пользователей, 1 гостей, 0 анонимных