Что нового

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

AZJIO

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

Вот:

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

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

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

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

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

Lazycat

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

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

AZJIO

Меценат
Меценат
Сообщения
2,892
Репутация
1,196
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
Репутация
626
AZJIO
Код:
_SQLite_Open()

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

AZJIO

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

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

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

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

kaster

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


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

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

AZJIO

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

kaster

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


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

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

Garrett

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

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

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