Что нового

[Процессы] Map Management - управление виртуальными файлами

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
В бета версии языка есть функции Map Management. Удобство их в том, что получить значение можно по имени ключа.
Не знаю как работают эти функции, но попробовал примерно реализовать это при помощи _WinAPI_CreateFileMapping
Код:
#include <WinApi.au3>
#include <WinAPIFiles.au3>
#include <GUIConstantsEx.au3>

Local $hMapping, $pAddress, $tData;используется для подключения к Map и считывания информации
;-Вариант создания карты, если входящие данные - массив(необязательно)
Local $ArrayDoc[3][2]
$ArrayDoc[0][0] = 'Первая запись'
$ArrayDoc[0][1] = 'Содержание первой записи'
$ArrayDoc[1][0] = 'Вторая запись'
$ArrayDoc[1][1] = 'Содержание второй записи'
$ArrayDoc[2][0] = 'Третья запись'
$ArrayDoc[2][1] = 'Содержание третьей записи'
For $i = 0 To UBound($ArrayDoc) - 1
	_CreateFileMap($ArrayDoc[$i][1], 'wchar', 'Doc', StringLen($ArrayDoc[$i][1]), '|', $ArrayDoc[$i][0])
Next
Local $ArrayDoc = 0
;----------------------------------------------------
$Form1 = GUICreate("Form1", 430, 150, 465, 179)
$Input1 = GUICtrlCreateInput("", 16, 24, 305, 21);вводится имя Map для чтения, создания или изменения
$Input2 = GUICtrlCreateInput("", 16, 117, 305, 21);получаем содержание при чтении или вводим содержание для записи
$Button1 = GUICtrlCreateButton("Читать", 344, 24, 75, 25);читать информацию из Map
$Button2 = GUICtrlCreateButton("Создать", 344, 54, 75, 25);создать Map
$Button3 = GUICtrlCreateButton("Изменить", 344, 84, 75, 25);чтобы изменить, нужно получить содержание Map
$Button4 = GUICtrlCreateButton("Удалить", 344, 114, 75, 25);чтобы удалить, нужно "Читать" Map
GUISetState(@SW_SHOW)

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
		Case $Button1
			_DisconnectFileMap($hMapping, $pAddress, $tData)
			_OpenFileMap($hMapping, $pAddress, $tData, GUICtrlRead($Input1))
			If Not @error Then
				GUICtrlSetData($Input2, $tData.Doc)
			Else
				MsgBox(16, 'Error', 'Not Found', 0, $Form1)
			EndIf
		Case $Button2
			$newname = StringStripWS(GUICtrlRead($Input1), 3)
			$newdata = StringStripWS(GUICtrlRead($Input2), 2)
			If Not $newdata = '' And Not $newdata = '' Then
				_CreateFileMap($newdata, 'wchar', 'Doc', StringLen($newdata), '|', $newname)
				If @error Then
					MsgBox(16, 'Error', 'Write Error', 0, $Form1)
				Else
					GUICtrlSetData($Input1, '')
					GUICtrlSetData($Input2, '')
					MsgBox(0, '!!!', 'Written', 0, $Form1)
				EndIf
			Else
				MsgBox(16, 'Error', 'Not Data', 0, $Form1)
			EndIf
		Case $Button3
			_DeleteFileMap($tData)
			If @error Then
				MsgBox(16, 'Error', 'Not Found', 0, $Form1)
			Else
				_DisconnectFileMap($hMapping, $pAddress, $tData)
				If @error Then
					MsgBox(16, 'Error', 'Not Found', 0, $Form1)
				Else
					$newname = StringStripWS(GUICtrlRead($Input1), 3)
					$newdata = StringStripWS(GUICtrlRead($Input2), 2)
					If Not $newdata = '' And Not $newdata = '' Then
						_CreateFileMap($newdata, 'wchar', 'Doc', StringLen($newdata), '|', $newname)
						If @error Then
							MsgBox(16, 'Error', 'Write Error', 0, $Form1)
						Else
							GUICtrlSetData($Input1, '')
							GUICtrlSetData($Input2, '')
							MsgBox(0, '!!!', 'Written', 0, $Form1)
						EndIf
					EndIf
				EndIf
			EndIf
		Case $Button4
			_DeleteFileMap($tData)
			If @error Then
				MsgBox(16, 'Error', 'Not Found', 0, $Form1)
			Else
				_DisconnectFileMap($hMapping, $pAddress, $tData)
				If @error Then
					MsgBox(16, 'Error', 'Not Found', 0, $Form1)
				Else
					GUICtrlSetData($Input1, '')
					GUICtrlSetData($Input2, '')
					MsgBox(0, '!!!', 'Removed', 0, $Form1)
				EndIf
			EndIf
	EndSwitch
WEnd

Func _OpenFileMap(ByRef $MapFile, ByRef $PosFile, ByRef $StructFile, $FileMapName = 'DataExchangeFile')
	Local $TempData, $TempInfData
	$MapFile = _WinAPI_OpenFileMapping($FileMapName)
	If $MapFile = 0 Then Return SetError(1)
	$PosFile = _WinAPI_MapViewOfFile($MapFile)
	If $PosFile = 0 Then Return SetError(2)
	Local $t_Data = DllStructCreate('int sol[10]', $PosFile)
	If @error Then Return SetError(3)
	$TempData = $t_Data.sol
	$t_Data = 0
	Local $tInfData = DllStructCreate('int sol[10];wchar info[' & $TempData & ']', $PosFile)
	If @error Then Return SetError(4)
	$TempInfData = $tInfData.info
	$tInfData = 0
	$StructFile = DllStructCreate('int sol[10];wchar info[' & $TempData & '];' & $TempInfData, $PosFile)
	If @error Then SetError(5)
EndFunc   ;==>_OpenFileMap

Func _CreateFileMap($IncomingData = '', $DataType = 'wchar', $ElementName = 'var', $ElementSize = 1024, $Separator = '|', $FileMapName = 'DataExchangeFile')
	Local $DataSize, $CreatedStruct, $InfoSizeStruct, $BaseStruct, $tagSTRUCT, $MapFile, $PosFile, $StructFile
	Local $SplitInData = StringSplit('||' & $IncomingData, $Separator)
	Local $SplitDataType = StringSplit('ptr|ptr|' & $DataType, $Separator);
	Local $SplitNameData = StringSplit('hMapping|pAddress|' & $ElementName, $Separator)
	Local $SplitSizeData = StringSplit('12|12|' & $ElementSize, $Separator)
	If $SplitInData[0] <> $SplitNameData[0] Or $SplitInData[0] <> $SplitDataType[0] Or $SplitInData[0] <> $SplitSizeData[0] Then Return SetError(1)
	For $i = 1 To $SplitInData[0]
		If $SplitDataType[$i] = '' Or $SplitNameData[$i] = '' Then ContinueLoop
		$DataNextElement = StringLen($SplitInData[$i])
		$DataSize += $DataNextElement
		If $SplitInData[$i] = '' And $SplitSizeData[$i] = '' Then
			$CreatedStruct &= $SplitDataType[$i] & ' ' & $SplitNameData[$i] & ';'
		ElseIf Not $SplitSizeData[$i] = '' Then
			$CreatedStruct &= $SplitDataType[$i] & ' ' & $SplitNameData[$i] & '[' & $SplitSizeData[$i] & ']' & ';'
		ElseIf Not $SplitInData[$i] = '' And $SplitSizeData[$i] = '' Then
			$CreatedStruct &= $SplitDataType[$i] & ' ' & $SplitNameData[$i] & '[' & $DataNextElement & ']' & ';'
		EndIf
	Next
	$CreatedStruct = StringTrimRight($CreatedStruct, 1)
	$InfoSizeStruct = StringLen($CreatedStruct)
	$BaseStruct = 'int sol[10];wchar info[' & $InfoSizeStruct & '];'
	$tagSTRUCT = $BaseStruct & $CreatedStruct
	$MapFile = _WinAPI_CreateFileMapping(-1, ($DataSize + $InfoSizeStruct) * 2 + 44, $FileMapName)
	If $MapFile = 0 Then Return SetError(2)
	$PosFile = _WinAPI_MapViewOfFile($MapFile)
	If $PosFile = 0 Then Return SetError(3)
	$StructFile = DllStructCreate($tagSTRUCT, $PosFile)
	If @error Then Return SetError(4)
	$StructFile.sol = $InfoSizeStruct
	$StructFile.info = $CreatedStruct
	For $i = 3 To $SplitInData[0]
		DllStructSetData($StructFile, $SplitNameData[$i], $SplitInData[$i])
	Next
	DllStructSetData($StructFile, $SplitNameData[1], $MapFile)
	DllStructSetData($StructFile, $SplitNameData[2], $PosFile)
EndFunc   ;==>_CreateFileMap

Func _DisconnectFileMap(ByRef $MapFile, ByRef $PosFile, ByRef $StructFile);отключение файла
	If Not _WinAPI_UnmapViewOfFile($PosFile) Then Return SetError(1)
	If Not _WinAPI_CloseHandle($MapFile) Then Return SetError(2)
	$StructFile = 0
EndFunc   ;==>_DisconnectFileMap

Func _DeleteFileMap($StructFile);удаление файла
	If Not _WinAPI_UnmapViewOfFile(DllStructGetData($StructFile, 'pAddress')) Then Return SetError(1)
	If Not _WinAPI_CloseHandle(DllStructGetData($StructFile, 'hMapping')) Then Return SetError(2)
EndFunc   ;==>_DeleteFileMap
 
Автор
joiner

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
использовать вызов значения из адресного пространства по имени "ключа" (вроде ж написал в первом сообщении)
ну и удалять. все в сравнении работы с массивом
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Это что очередное key value хранилище, но вы сделали это через _WinAPI_CreateFileMapping и зачем? Только что бы было? :smile:
Вот вам еще одно такое же...

Код:
set('dddd', 123)
ConsoleWrite(get('dddd') & @CRLF)
Func set($data, $value)
	Assign('_storage_' & $data, $value, 2)
EndFunc
Func get($data)
	Return Eval('_storage_' & $data)
EndFunc
 
Автор
joiner

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
пример чуть переделал
Код:
#include <WinApi.au3>
#include <WinAPIFiles.au3>
#include <GUIConstantsEx.au3>

Local $hMapping, $pAddress, $tData;используется для подключения к Map и считывания информации
;-Вариант создания карты, если входящие данные - массив(необязательно)
$t = TimerInit()
Local $ArrayDoc[0][2]
For $i = 0 To 10000
	ReDim $ArrayDoc[$i + 1][2]
	$ArrayDoc[$i][0] = 'док' & $i + 1
	$ArrayDoc[$i][1] = 'содержание' & $i + 1
Next
ConsoleWrite(TimerDiff($t) & ' - 1' & @LF)
$t = TimerInit()
For $i = 1 To 10000
	_CreateFileMap($ArrayDoc[$i][1], 'wchar', 'Doc', $ArrayDoc[$i][0])
Next
ConsoleWrite(TimerDiff($t) & ' - 2' & @LF)
;----------------------------------------------------
$Form1 = GUICreate("Form1", 430, 150, 465, 179)
$Input1 = GUICtrlCreateInput("", 16, 24, 305, 21);вводится имя Map для чтения, создания или изменения
$Input2 = GUICtrlCreateInput("", 16, 117, 305, 21);получаем содержание при чтении или вводим содержание для записи
$Button1 = GUICtrlCreateButton("Читать", 344, 24, 75, 25);читать информацию из Map
$Button2 = GUICtrlCreateButton("Создать", 344, 54, 75, 25);создать Map
$Button3 = GUICtrlCreateButton("Изменить", 344, 84, 75, 25);чтобы изменить, нужно получить содержание Map
$Button4 = GUICtrlCreateButton("Удалить", 344, 114, 75, 25);чтобы удалить, нужно "Читать" Map
GUISetState(@SW_SHOW)

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
		Case $Button1
			$name = GUICtrlRead($Input1)
			$t = TimerInit()
			For $i = 0 To UBound($ArrayDoc) - 1
				If Not StringCompare($name, $ArrayDoc[$i][0]) Then ConsoleWrite($ArrayDoc[$i][1] & @LF)
			Next
			ConsoleWrite(TimerDiff($t) & ' - 3' & @LF)
			_DisconnectFileMap($hMapping, $pAddress, $tData)
			$t = TimerInit()
			_OpenFileMap($hMapping, $pAddress, $tData, $name)
			If Not @error Then
				GUICtrlSetData($Input2, $tData.Doc)
				ConsoleWrite(TimerDiff($t) & ' - 4' & @LF)
			Else
				MsgBox(16, 'Error', 'Not Found', 0, $Form1)
			EndIf
		Case $Button2
			$newname = StringStripWS(GUICtrlRead($Input1), 3)
			$newdata = StringStripWS(GUICtrlRead($Input2), 2)
			If Not $newdata = '' And Not $newdata = '' Then
				_CreateFileMap($newdata, 'wchar', 'Doc', $newname)
				If @error Then
					MsgBox(16, 'Error', 'Write Error', 0, $Form1)
				Else
					GUICtrlSetData($Input1, '')
					GUICtrlSetData($Input2, '')
					MsgBox(0, '!!!', 'Written', 0, $Form1)
				EndIf
			Else
				MsgBox(16, 'Error', 'Not Data', 0, $Form1)
			EndIf
		Case $Button3
			_DeleteFileMap($tData)
			If @error Then
				MsgBox(16, 'Error', 'Not Found', 0, $Form1)
			Else
				_DisconnectFileMap($hMapping, $pAddress, $tData)
				If @error Then
					MsgBox(16, 'Error', 'Not Found', 0, $Form1)
				Else
					$newname = StringStripWS(GUICtrlRead($Input1), 3)
					$newdata = StringStripWS(GUICtrlRead($Input2), 2)
					If Not $newdata = '' And Not $newdata = '' Then
						_CreateFileMap($newdata, 'wchar', 'Doc', $newname)
						If @error Then
							MsgBox(16, 'Error', 'Write Error', 0, $Form1)
						Else
							GUICtrlSetData($Input1, '')
							GUICtrlSetData($Input2, '')
							MsgBox(0, '!!!', 'Written', 0, $Form1)
						EndIf
					EndIf
				EndIf
			EndIf
		Case $Button4
			_DeleteFileMap($tData)
			If @error Then
				MsgBox(16, 'Error', 'Not Found', 0, $Form1)
			Else
				_DisconnectFileMap($hMapping, $pAddress, $tData)
				If @error Then
					MsgBox(16, 'Error', 'Not Found', 0, $Form1)
				Else
					GUICtrlSetData($Input1, '')
					GUICtrlSetData($Input2, '')
					MsgBox(0, '!!!', 'Removed', 0, $Form1)
				EndIf
			EndIf
	EndSwitch
WEnd

Func _OpenFileMap(ByRef $MapFile, ByRef $PosFile, ByRef $StructFile, $FileMapName = 'DataExchangeFile')
	Local $TempData, $TempInfData
	$MapFile = _WinAPI_OpenFileMapping($FileMapName)
	If $MapFile = 0 Then Return SetError(1)
	$PosFile = _WinAPI_MapViewOfFile($MapFile)
	If $PosFile = 0 Then Return SetError(2)
	Local $t_Data = DllStructCreate('int sol[10]', $PosFile)
	If @error Then Return SetError(3)
	$TempData = $t_Data.sol
	$t_Data = 0
	Local $tInfData = DllStructCreate('int sol[10];wchar info[' & $TempData & ']', $PosFile)
	If @error Then Return SetError(4)
	$TempInfData = $tInfData.info
	$tInfData = 0
	$StructFile = DllStructCreate('int sol[10];wchar info[' & $TempData & '];' & $TempInfData, $PosFile)
	If @error Then SetError(5)
EndFunc   ;==>_OpenFileMap

Func _CreateFileMap($IncomingData = '', $DataType = 'wchar', $ElementName = 'var', $FileMapName = 'DataExchangeFile')
	Local $DataSize, $CreatedStruct, $InfoSizeStruct, $BaseStruct, $tagSTRUCT, $MapFile, $PosFile, $StructFile
	$CreatedStruct = 'ptr hMapping[12];ptr pAddress[12];' & $DataType & ' ' & $ElementName & '[' & StringLen($IncomingData) & ']'
	$InfoSizeStruct = StringLen($CreatedStruct)
	$BaseStruct = 'int sol[10];wchar info[' & $InfoSizeStruct & '];'
	$tagSTRUCT = $BaseStruct & $CreatedStruct
	$MapFile = _WinAPI_CreateFileMapping(-1, ($DataSize + $InfoSizeStruct) * 2 + 44, $FileMapName)
	If $MapFile = 0 Then Return SetError(2)
	$PosFile = _WinAPI_MapViewOfFile($MapFile)
	If $PosFile = 0 Then Return SetError(3)
	$StructFile = DllStructCreate($tagSTRUCT, $PosFile)
	If @error Then Return SetError(4)
	$StructFile.sol = $InfoSizeStruct
	$StructFile.info = $CreatedStruct
	DllStructSetData($StructFile, $ElementName, $IncomingData)
	DllStructSetData($StructFile, 'hMapping', $MapFile)
	DllStructSetData($StructFile, 'pAddress', $PosFile)
EndFunc   ;==>_CreateFileMap

Func _DisconnectFileMap(ByRef $MapFile, ByRef $PosFile, ByRef $StructFile);отключение файла
	If Not _WinAPI_UnmapViewOfFile($PosFile) Then Return SetError(1)
	If Not _WinAPI_CloseHandle($MapFile) Then Return SetError(2)
	$StructFile = 0
EndFunc   ;==>_DisconnectFileMap

Func _DeleteFileMap($StructFile);удаление файла
	If Not _WinAPI_UnmapViewOfFile(DllStructGetData($StructFile, 'pAddress')) Then Return SetError(1)
	If Not _WinAPI_CloseHandle(DllStructGetData($StructFile, 'hMapping')) Then Return SetError(2)
EndFunc   ;==>_DeleteFileMap
взято сравнение составление массива с заполнением и создание виртуальных файлов
результаты теста
61494.1353058005 - составление массива 10 000 элементов с заполнением
2609.35162699179 - создание 10 000 вирт. файлов с заполнением
19.8788554902482 - поиск последнего элемента в массиве по имени
0.507613520065925 - выведение значения по имени вирт. файла
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Если вы так составляете массив из известного количества элементов:
Код:
For $i = 0 To 10000
    ReDim $ArrayDoc[$i + 1][2] ;Внимание аноним, это ахтунг. Никогда так не писать!
    $ArrayDoc[$i][0] = 'док' & $i + 1
    $ArrayDoc[$i][1] = 'содержание' & $i + 1
Next

то у меня для вас печальные новости ;D
У меня массив из 10 тыс элементов составляется за 79.208 мс.
 
Автор
joiner

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
inververs [?]
то у меня для вас печальные новости
неужели? :smile:
а я разве говорил, что заранее известно? ведь специально указал
Код:
ReDim
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
:rofl:
REDIM в вашем цикле это 10000 повторить операцию: сохранить где то данные, очистить массив, создать массив на 1 больше, заполнить его ранее созданными данными, дописать в конец еще 'док' & $i + 1. и так 10000 раз. Вам может быть не понятно, но redim в цикле это как бегать 10000 раз в магазин покупая по 1 предмету.
И мне кажется For $i=1 To 10000 и
joiner [?]
что заранее известно
как то противоречат друг другу.


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

В общем, что хочу сказать. Что ваши тесты не коректны.
 
Автор
joiner

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
inververs [?]
как то противоречат друг другу.
повторю еще раз
специально указал ReDim, подразумевая, что неизвестно конечное количество строк массива.но пример ограничил в 10 000 строк. я знаю принцип работы пересоздания массива
OffTopic:
вроде на русском общаемся


[?]
;Внимание аноним, это ахтунг. Никогда так не писать!
здесь поясни. почему так нельзя писать



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

пример в первом сообщении написал исходя из своего проекта. смысл в том, чтобы иметь не одно значение, а несколько. для этого использовал структуру как хранилище.
подключаюсь к вирт. файлу по имени (имя может иметь различные символы любого языка). подключился и получил структуру, в которой может быть несколько значений .
возможно, мой вариант не оптимальный.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
joiner,
А чем Вас не устраивает Scripting.Dictionary, если Вы не хотите использовать Map* функции из бета-версии?
 
Автор
joiner

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
я сторонник нативных функций. и воспользовался бы Map из бета-версии, но в бетке есть серьезный баг работы с файловой системой(обсуждали в теме бета-версий), а для меня это решающий момент использование версии языка.

madmasles [?]
А чем Вас не устраивает Scripting.Dictionary
да я не против. просто изобразил по своему

P.S.если все как-то никак, то могу удалить тему.в принципе, все преходящее
 
Верх