Что нового

Package UDF - Создание собственных PKR архивов

Автор
Yashied

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Проблема в следующем:

Код:
For $i = 1 To UBound($f_s) - 1
	...
	
	$array[$i - 1] = StringRegExpReplace($f_s[$i], '.*' & $folder_name[1], '')
	
	...
Next


Код:
For $i = 1 To UBound($array) - 1
    $n_f = _FO_PathSplit($array[$i])
    DirCreate($path_unpack & '\' & $folder_name[1] & $n_f[0])
Next


Увидели? Если нет, то поясню. Вы начинаете перечислять пути в массиве $array, начиная с индекса 1:

Код:
For $i = 1 To UBound($array) - 1


Но первый действительный путь находится под индексом 0:

Код:
For $i = 1 To UBound($f_s) - 1


и

Код:
$array[$i - 1] = StringRegExpReplace($f_s[$i], '.*' & $folder_name[1], '')


Таким образом происходит нессответствие путей и файлов в архиве, что и приводит к неправильному извлечению файлов и, как следствие, к ошибке.

P.S.

Если хотите сохранить структуру папок, то записывайте путь в архив.
 

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
Yashied [?]
Если хотите сохранить структуру папок, то записывайте путь в архив.
видимо я что то пропустил. не увидел параметра, где подразумевается запись дерева папок в архив.
насчет неверных путей, то функция должна выдавать ошибку и так весь цикл, пока не будет достигнут конец массива. но не зависать
насчет перечислений путей, то в первую папку копируются все файлы. и во вторую и так далее.
функция
Код:
$f_s = _FO_FileSearch($File, '*')

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

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
joiner сказал(а):
видимо я что то пропустил. не увидел параметра, где подразумевается запись дерева папок в архив
Туда же, куда и имя файла. Например так:

DirA\DirB\DirC\File.txt

joiner сказал(а):
Код:
$f_s = _FO_FileSearch($File, '*')

возвращает массив в таком исполнении, где в первой строке находится количество строк. поэтому начинается перечисление не с нулевого индекса

Речь не о $f_s, а о вашем массиве $array, в котором сохраняются пути при занесении файлов в архив, начиная с индекса 0. При извлечении файлов, вы начинаете перечислять пути с индекса 1, в то время, как первый файл в архиве соответствует пути в нулевой ячейке массива. У вас получается такая картина: 1 - 0, 2 - 1, 3 - 2 и т.д., а должно быть 0 - 0, 1 - 1, 2 - 2 и т.д.

И с чего вы взяли, что функция зависает? Просто запись на диск происходит в несколько раз медленнее. В данном случае у меня получилось 2 сек на запись в архив и 5 сек на извлечение.
 

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
Yashied [?]
И с чего вы взяли, что функция зависает? Просто запись на диск происходит в несколько раз медленнее. В данном случае у меня получилось 2 сек на запись в архив и 5 сек на извлечение.
просто, 690 мб функция извлекает секунд за двадцать ( не засекал точно) а на последних 20мб происходит зависание.. файлы малого размера, да и напряг процессора внушительный для записи файла в пару мб
насчет записи пути в архив понял..завтра перепишу код..
спасибо за разъяснения
 
Автор
Yashied

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Вообще, это все делается с помощью рекурсии примерно так:

Код:
#Include <Package.au3>
#Include <WinAPIEx.au3>

Global $hPackage, $Data, $Root, $Path

$Root = FileSelectFolder('Select folder for packing.', '', 2, @ScriptDir)
If Not $Root Then
	Exit
EndIf

If _WinAPI_PathIsDirectoryEmpty($Root) Then
	MsgBox(16, 'Error', 'Folder is empty.')
	Exit
EndIf

$hPackage = _PK_Create(@ScriptDir & '\Test.pkr', '', 1)
If @Error Then
;	ConsoleWrite('Error: ' & @Error & @CR)
	Exit
EndIf

If Not _Enum($Root) Then
	; Error
	Exit
EndIf

_PK_DisplayPackage($hPackage, $Root)

_PK_Close($hPackage)

$Root = FileSelectFolder('Select folder for unpacking archive.', '', 2, @ScriptDir)
If Not $Root Then
	Exit
EndIf

$hPackage = _PK_Open(@ScriptDir & '\Test.pkr')
If @Error Then
;	ConsoleWrite('Error: ' & @Error & @CR)
	Exit
EndIf

$Data = _PK_EnumPackets($hPackage)
If @Error Then
;	ConsoleWrite('Error: ' & @Error & @CR)
	Exit
EndIf

For $i = 1 To $Data[0][0]
	$Path = _WinAPI_PathRemoveFileSpec($Data[$i][1])
	If (Not FileExists($Root & $Path)) And (Not DirCreate($Root & $Path)) Then
		; Error
		Exit
	EndIf
	If StringRight($Data[$i][1], 1) <> '\' Then
		_PK_ExtractPacketDataToFile($hPackage, $Data[$i][0], $Root & $Data[$i][1])
		If @Error Then
;			ConsoleWrite('Error: ' & @Error & ' - ' & $Root & $Data[$i][1] & @CR)
			Exit
		EndIf
	EndIf
Next

_PK_Close($hPackage)

ShellExecute($Root)

Func _Enum($sRoot, $sPath = '')

	Local $hSearch, $File, $Result = 1

	$hSearch = FileFindFirstFile($sRoot & '\' & $sPath & '\*')
	If $hSearch = -1 Then
		If @Error Then
			If $sPath Then
				_PK_AddPacket($hPackage, 0, 0, $sPath & '\')
				If @Error Then
;					ConsoleWrite('Error: ' & @Error & ' - ' & $sPath & '\' & @CR)
					Return 0
				EndIf
				Return 1
			Else
				Return 0
			EndIf
		Else
			Return 0
		EndIf
	EndIf
	While 1
		$File = FileFindNextFile($hSearch)
		If @Error Then
			ExitLoop
		EndIf
		If @Extended Then
			If Not _Enum($sRoot, $sPath & '\' & $File) Then
				$Result = 0
				ExitLoop
			EndIf
		Else
			_PK_AddPacketFromFile($hPackage, $sRoot & '\' & $sPath & '\' & $File, $sPath & '\' & $File, 1)
			If @Error Then
;				ConsoleWrite('Error: ' & @Error & ' - ' & $sPath & '\' & $File & @CR)
				$Result = 0
				ExitLoop
			EndIf
		EndIf
	WEnd
	FileClose($hSearch)
	Return $Result
EndFunc   ;==>_Enum


По поводу скорости. Эта библиотека не была предназначена для создания больших архивов с большим количеством данных. Для этого есть множество сторонних инструментов. Package UDF разрабатывалась как подспорье для упрощения проектов, написанных на AutoIt. Хороший пример использования данной библиотеки - объединение файлов оформления GUI (skin) в один архив. На данный момент падение скорости при извлечении данных будет тем больше, чем выше порядковый номер пакета (файла) в архиве.
 

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
сделал я запись путей в архив. теперь и правда стало все намного проще при распаковке.
но проблема с замедлением распаковки остается.
я упоминал уже, что запаковываю в архив множество мелковесных файлов. общий размер 700мб..число файлов 4300.
замедление происходит после распаковки 690мб. при этом распаковывается около 1500 файлов.
при этом расход системной памяти не увеличивается, но занятость процессора 50-60%.
где то функция распаковки входит в ступор,видимо..зависания нет. файлы так же распаковываются, но ,как я уже писал, очень медленно.

Yashied [?]
На данный момент падение скорости при извлечении данных будет тем больше, чем выше порядковый номер пакета (файла) в архиве.
да, как раз проблема в этом. можно ли это исправить? тогда вообще был бы "шик-блеск-красота" . :smile:
 
Автор
Yashied

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Программы, написанные на AutoIt, являются однопоточными и используют ЦП соответственно. Такая загрузка явялется нормальной, и говорит о том, что программа работает.

Еще раз про падение скорости. Технически, для извлечения каждого пакета необходимо сначала найти его в архиве, последовательно перечислив все пакеты, располагающиеся до искомого пакета. Таким образом получается, что чем дальше от начала файла находится извлекаемый пакет, тем больше времени потребуется на его поиск. Размер пакета особой роли не играет. Чтобы существенно сократить время поиска, нужно менять структуру архива и водить внутреннюю таблицу адресов пакетов в файле, что вызовет ряд новых проблем. В любом случае, в ближайшее время я это не планирую делать, т.к. изначально Package UDF не предназначалась для подобных задач.
 
Верх