Что нового

[Автоматизация] Создание алгоритма программы поиска дубликатов файлов

AZJIO

Меценат
Меценат
Сообщения
2 752
Репутация
1 149
Прежде чем браться за написание кода программы, решил предложить пофилосовствовать над алгоритмом программы. Пока что он мне не по зубам без предварительного плана.

Вот:

1. Представление данных, массив вида
а) абсолютный_путь-файл|размер|контрольная сумма|индекс добавления каталога|Приоритет удаления
б) Первый проход - отсеивание файлов по размеру, чтобы не хешировать лишние мегадайты, на втором проходе создание полного массива с вычислением контрольных сумм.

2. С помощью Assing отсеиваются файлы, размер которых в массиве в одном экземпляре.
С помощью Assing те элементы, в которых контрольная сумма повторяется более 1 раза, присоединяются в строку с разделителем. Далее эти группы сплитятся в массив и наполняются в ListView группами.

3. Получаем на выходе окно с отмеченными чекбоксами, и далее кнопкой в цикле выполняем удаление отмеченных.

4. Если ListView из UDF, то цикл удаления начинать с конца, так как удаляемые от начала нарушат индексы последующих.

5. Второстепенные фичи: клик в окне для открытия файла (каталога файла), копирование/перемещение отмеченных со структурой каталогов в указанную папку.
 

Lazycat

Осваивающий
Сообщения
46
Репутация
21
Можно, конечно, делать все на чистом автоите, но думаю перелопачивание больших списков займет немало времени (это что касается пунктов 2 и 3).

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

AZJIO

Меценат
Меценат
Сообщения
2 752
Репутация
1 149
Loopback
Я ни разу не пользовался SQLite, не понимаю как это работает и в чём отличие. У меня установлен сервер mysql и я как то привык считать, что это некая программа, которая содержит базу данных и умеет выполнять запросы при обращении к ней.
Скрипт-пример найденный в инете показал обычное добавление данных в файл, и я даже не проверял, использует ли он запущенную у меня службу mysql. В общем я по этой теме ничего не понимаю. Где хранится база, в памяти или в файле на харде.
Пока безуспешно пытался создать массив $FileList=_FileListToArray('C:\Program Files','*.*',2) работает, но без вложенных каталогов.

Не думаю, что в "DupeLocater 2" (176кб, Microsoft Visual C++ 6.0) используется SQLite.


Проверил скрипт SQLite:
Код:
#NoTrayIcon
#include <GUIListBox.au3>
#include <GuiListView.au3>
#include <SQLite.au3>
#include <SQLite.dll.au3>
Opt("GUICloseOnESC", 1) ; выход по ESC
;Global $GUI_ListBox
;Global $GUI_Input1, $GUI_Input2, $GUI_Input3, $GUI_Input4, $GUI_Input5
;Global $Open, $Insert, $Select, $Delete
Global $Msg, $hQuery, $aRow
Global $Temp, $a, $b, $c
$SQLite_Data_Path = "SQLite.db"
_SQLite_Startup() ; загрузка SQLite.dll в память (2мб)
$GUI_Form = GUICreate("SQLite пример", 320, 460)
GUISetBkColor(0xECE9D8) ; цвет фона программы
$GUI_ListBox = GUICtrlCreateListView("", 2, 2, 316, 309, 0x0010)
_GUICtrlListView_AddColumn($GUI_ListBox, "№ Add", 80, 0)
_GUICtrlListView_AddColumn($GUI_ListBox, "№ Del, Sel", 100, 1)
_GUICtrlListView_AddColumn($GUI_ListBox, "Данные", 120, 1)
GUICtrlCreateLabel("Добавляем эти данные в базу", 44, 352, 210, 15)
$GUI_Input1 = GUICtrlCreateInput("", 10, 368, 73, 20)
$GUI_Input2 = GUICtrlCreateInput("", 88, 368, 73, 20)
$GUI_Input3 = GUICtrlCreateInput("", 166, 368, 73, 20)
$GUI_Input4 = GUICtrlCreateInput("", 88, 393, 73, 20)
$GUI_Input5 = GUICtrlCreateInput("", 88, 418, 73, 20)
$Create = GUICtrlCreateButton("Создать", 246, 317, 68, 22, 0)
GUICtrlSetTip(-1, 'Создать пустую базу в файле')
$Open = GUICtrlCreateButton("Открыть", 246, 342, 68, 22, 0)
GUICtrlSetTip(-1, 'Открыть базу из файла')
$Insert = GUICtrlCreateButton("Добавить", 246, 367, 68, 22, 0)
GUICtrlSetTip(-1, 'Добавляем элемент')
$Select = GUICtrlCreateButton("Выделить", 246, 392, 68, 22, 0)
GUICtrlSetTip(-1, 'Выбираем элемент')
$Delete = GUICtrlCreateButton("Удалить", 246, 417, 68, 22, 0)
GUICtrlSetTip(-1, 'Удаляем элемент по второй колонке')
GUICtrlCreateGroup("", 2, 307, 316, 134)
GUICtrlCreateLabel("здесь была база данных SQL", 72, 446, 240, 15)
GUICtrlSetState(-1, $GUI_DISABLE)
GUISetState()

While 1
	$Msg = GUIGetMsg()
	Select
		Case $Msg = $Create ; читаем базу из файла
			$SQLite_Data_Path = FileSaveDialog("Выбор файла сохранения", @ScriptDir & "", "файл база (*.db)", 24, 'SQLite.db')
			If @error Then ContinueLoop
			If Not FileExists($SQLite_Data_Path) Then CreateSQL($SQLite_Data_Path) ; если не существует базы создаём её.
		Case $Msg = $Open ; читаем базу из файла
			$SQLite_Data_Path = FileOpenDialog("Выбрать файл", @WorkingDir & "", "Все файлы (*.*)", 1 + 4)
			ReadSQL()
		Case $Msg = $Insert
			Insert(GUICtrlRead($GUI_Input1), GUICtrlRead($GUI_Input2), GUICtrlRead($GUI_Input3)) ; добавляем элемент
			ReadSQL()
		Case $Msg = $Select ; выбираем элемент
			SelectItemSQL(GUICtrlRead($GUI_Input4))
		Case $Msg = $Delete ; удаляем элемент
			DeleteItemSQL(GUICtrlRead($GUI_Input5))
			ReadSQL()
		Case $Msg = -3 ; выход
			_SQLite_Shutdown() ; вызрузка SQLite.dll
			ExitLoop
	EndSelect

WEnd

Func CreateSQL($SQLite_Path) ; функция создания файла базы
	_SQLite_Open($SQLite_Path)
	_SQLite_Exec(-1, "Create Table IF NOT Exists TestTable (IDs Text PRIMARY KEY, Name Text, Age Text);")
	_SQLite_Close()
EndFunc

Func ReadSQL() ; функция чтения данных файла базы
	_GUICtrlListView_DeleteAllItems(GUICtrlGetHandle($GUI_ListBox))
	_SQLite_Open($SQLite_Data_Path)
	_SQLite_Query(-1, "SELECT * FROM TestTable ORDER BY IDs DESC;", $hQuery)
	While _SQLite_FetchData($hQuery, $aRow) = $SQLITE_OK
		_GUICtrlListView_AddItem($GUI_ListBox, $aRow[0])
		_GUICtrlListView_AddSubItem($GUI_ListBox, _GUICtrlListView_FindInText($GUI_ListBox, $aRow[0]), $aRow[1], 1)
		_GUICtrlListView_AddSubItem($GUI_ListBox, _GUICtrlListView_FindInText($GUI_ListBox, $aRow[0]), $aRow[2], 2)
	WEnd
	_SQLite_Close()
EndFunc

Func Insert($a, $b, $c) ; функция добавления элементов в файл базы
	_SQLite_Open($SQLite_Data_Path)
	_SQLite_QuerySingleRow(-1, "SELECT IDs FROM TestTable WHERE IDs = '" & $a & "';", $aRow)
	$Temp = $aRow[0]
	If $Temp = "" Then
		_SQLite_Exec(-1, "Insert into TestTable (IDs) values ('" & $a & "');")
	EndIf
	_SQLite_Exec(-1, "UPDATE TestTable SET Name = '" & $b & "' WHERE IDs = '" & $a & "';")
	_SQLite_Exec(-1, "UPDATE TestTable SET Age = '" & $c & "' WHERE IDs = '" & $a & "';")
	_SQLite_Close()
EndFunc

Func SelectItemSQL($a) ; функция выбора элемента файла базы
	_SQLite_Open($SQLite_Data_Path)
	_SQLite_QuerySingleRow(-1, "SELECT * FROM TestTable WHERE Name = '" & $a & "';", $aRow)
	$Temp = $aRow[0]
	If $Temp = "" Then
		MsgBox(262208, "Сообщение...", "Нет таких данных [" & $a & "] блин!")
	Else
		_GUICtrlListView_DeleteAllItems(GUICtrlGetHandle($GUI_ListBox))
		_GUICtrlListView_AddItem($GUI_ListBox, $aRow[0])
		_GUICtrlListView_AddSubItem($GUI_ListBox, _GUICtrlListView_FindInText($GUI_ListBox, $aRow[0]), $aRow[1], 1)
		_GUICtrlListView_AddSubItem($GUI_ListBox, _GUICtrlListView_FindInText($GUI_ListBox, $aRow[0]), $aRow[2], 2)
		MsgBox(262208, "Сообщение...", "Оставлено: 1=[" & $aRow[0] & "] 2=[" & $aRow[1] & "] 3=[" & $aRow[2] & "] !")
	EndIf
	_SQLite_Close()
EndFunc

Func DeleteItemSQL($a) ; функция удаления элемента файла базы
	_SQLite_Open($SQLite_Data_Path)
	_SQLite_Exec(-1, "DELETE FROM TestTable WHERE Name = '" & $a & "';")
	_SQLite_Close()
	MsgBox(262208, "Сообщение...", "Удаляем ячейку [" & $a & "] и обновляем данные в списке.")
EndFunc

Сохраняет в файл, хотелось бы выполнять все действия в памяти, обращение к харду тормозит любую операцию.
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
AZJIO
Код:
_SQLite_Open()

без параметров создает базу в памяти
 
Автор
A

AZJIO

Меценат
Меценат
Сообщения
2 752
Репутация
1 149
Kaster
Посмотрел в справке и UDF в Include, в функциях не увидел сортировки, поиск "sort" в UDF результатов не дал. Искал в последней версии v3.3.6.1.

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

Или всё же сама сортировка отнимет не меньше ресурсов проца и не стоит на ней зацикливаться и попробовать выполнять поиск по базе SQL?

То есть поиск по колонке размеров, и далее по колонке md5 с индексами соответствующие найденным размерам...
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
AZJIO
в базах данных сортировка ни к чему. данные там хранятся по другому алгоритму, и доступ к ним идет иначе. язык запросов устроен таким образом, что все необходимые оптимизации по поиску данных уже сделаны.
сортировать можно только визуально, для восприятия человеком - для этого существуют свои запросы. вобщем, почитай азы SQL, многие вопросы отпадут сами собой.
но одно могу сказать точно - при работе с большим объемом хранимой информации ничто не сравнится с sql, т.к. он заточен именно под такие нужды


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

ты про сортировку массивов?
может это?
Код:
_ArraySort
 
Автор
A

AZJIO

Меценат
Меценат
Сообщения
2 752
Репутация
1 149
Kaster
Немного понял, в файле SQLite.dll.au3 содержится двухмегабайтная библиотека для загрузки в память и вызов функций на языке SQLite с помощью _SQLite_Exec. Кстати скомпилированный скрипт 1.4Мб.
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
AZJIO
эта библиотека - есть бинарная запись файла sqlite.dll. Я так понял, что она предназначена для тех, у кого нет этой самой дллки. но в общем и целом, она бесполезна


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

хотя нет, как раз таки вот для таких целей -
скомпилированный скрипт 1.4Мб.
наверное и полезно, т.к. текст сжимается на порядки лучше бинарников
 

Garrett

Модератор
Локальный модератор
Сообщения
3 999
Репутация
964
AZJIO
SQLite - эта база данных хранит свои записи в файлах на диске с расширением *.db
Она использует стандартный язык SQL запросов реляционных баз данных (так же как и MySQL)
sqlite.dll - должна присутствовать в каталоге со скриптом или быть зарегистрирована в системе.
sqlite.exe - "command-line program"
Вся документация работы с dll и exe есть на сайте.
 
Б

Безымянный_герой

Гость
Пофилософствовали, и все? Жаль, что пропала охота писать скрипт. Это было бы почти готовым решением моей задачи, см. стол заказов & "//" & "поиск файлов на диске по нестандартному шаблону"
 
Верх