1 (изменено: __Михаил__, 2024-11-11 02:50:57)

Тема: AHK: Извлечь Hex данные из файла

Удалось немного ускорить процесс извлечения 'Hex' из файла. Надеюсь всё верно написал (процентное соотношение скорости обработки функций например).

#SingleInstance Force
#NoEnv
SetBatchLines -1
SetWorkingDir %A_ScriptDir%
Menu, Tray, Click, 1


File := "123.mp3"			; Размер файла:	1.87 Мб.
;File := "Kub0 - In The Dark.mp3"	; Размер файла:	10.1 Мб.

;-------------------------
ToolTip, [Обработка], 0, 0

TTime(0)	; Начать отсчёт времени.
A1 := GetHexData(File)
T1 := TTime(1)	; Завершить отсчёт.

TTime(0)
A2 := OpenHex(File)
T2 := TTime(1)

AA := ["Да", "Нет"][2 - (A1 = A2)]	; Проверка на совпадение 'Hex' данных.
P := Procent(T1, T2, 2, 1)		; Разница в процентах.

/*
; Для проверки - сохранить в файл Hex данные:
ToolTip, [Сохранение 1], 0, 0
WriteHex(A1, "Test A1.mp3")

ToolTip, [Сохранение 2], 0, 0
WriteHex(A2, "Test A2.mp3")
*/
ToolTip
MsgBox, % File "`n`nGetHexData:`t" T1 "мс.`nOpenHex:`t" T2 "мс.`n`nСовпало:`t" AA "`nРазница: `t" P
Return


;============================================================================================================================================
;[teadrinker] 02.08.2013	http://forum.script-coding.com/viewtopic.php?pid=74189#p74189
; Извлекает 'Hex' строку из файла. HexDataFile - путь вывода в файл (если нужно), Del - делитель (если нужно).
GetHexData(SourseFile, HexDataFile = 0, Del = ""){
 BinaryStream := ComObjCreate("ADODB.Stream")
 BinaryStream.Type := 1 ; adTypeBinary
 BinaryStream.Open
 BinaryStream.LoadFromFile(SourseFile)
 BinaryArray := BinaryStream.Read
 BinaryStream.Close
 R := A_FormatInteger		; Сохр. формат представления.
 SetFormat, IntegerFast, H
 Loop % BinaryArray.MaxIndex() + 1
  Text .= (A_Index = 1 ? "" : Del) . SubStr("0" . SubStr(BinaryArray[A_Index-1]+0, 3), -1)
 If (HexDataFile = 0){	; Если путь не указан - вернуть строку:
  SetFormat, IntegerFast, % R
  Return Text
 }
 File := FileOpen(HexDataFile, "w")
 File.Write(Text)
 File.Close()
 SetFormat, IntegerFast, % R
}


OpenHex(File){ ;23:17 10.11.2024	Ускоренная версия:
 File := FileOpen(File, "r"), File.Pos := 0, File.RawRead(Buf, Length := File.Length), File.Close(), F := A_FormatInteger
 SetFormat, IntegerFast, Hex
 Loop % Length
  R := SubStr(NumGet(Buf, A_Index - 1, "UChar"), 3), Hex .= (StrLen(R) < 2 ? "0" R : R)
 SetFormat, IntegerFast, % F
 Return Hex
}

; 09:08 27.04.2022	Сохранить 'Hex' в файл.
WriteHex(HexStr, Path = "WriteHex.txt"){
 File := FileOpen(Path, "w")
 While(I := SubStr(HexStr, A_Index*2-1, 2)) != ""
  File.WriteUChar("0x" I)
 File.Close()
}

;23:29 03.01.2022	Для быстрого определения прошедшего времени для команд. Без ограничений для отсчёта разниц.
;M: 0:Начать отсчёт, 1:Вернуть разницу. I - индекс в массиве таймингов.
TTime(M := 1, I := 1){
 Static C := {}
 Return (M ? A_TickCount-C[i] : C[i] := A_TickCount)	; Сокращённый вариант.
}

;01:15 11.11.2024 Доработка: автоматически сравнивает меньшее от большего. Compare - отвечает за сравнение разницы чисел.
Procent(n1, n2, R := 2, Compare = 0){
 P := (Min(n1, n2) / Max(n1, n2)) * 100
 If (Compare)
  P := 100 - P
 Return ARound(P, R) "%"
}

; Округление числа до R знаков после запятой +удаление лишних нулей и точки, если она осталась.
ARound(N, R := 2){ ; N:Число, R:Округление после запятой.
 Return RTrim(RTrim(Round(N, R), "0"), ".")
}
Процессор:	AMD Ryzen 5 5600.
Тест при разных настройках в Электропитании помпа:
-------------------------	Файл: 123.mp3
-	CPU Eco:	-
GetHexData:	3829мс.
OpenHex:	2296мс.
Разница: 	40.04%

GetHexData:	3735мс.
OpenHex:	2312мс.
Разница: 	38.1%

GetHexData:	2047мс.
OpenHex:	1297мс.
Разница: 	36.64%
-------------------------
-	CPU Balance:	-
GetHexData:	2063мс.
OpenHex:	1281мс.
Разница: 	37.91%

GetHexData:	2031мс.
OpenHex:	1219мс.
Разница: 	39.98%

GetHexData:	2062мс.
OpenHex:	1235мс.
Разница: 	40.11%
-------------------------
-	CPU Max:	-
GetHexData:	1453мс.
OpenHex:	875мс.
Разница: 	39.78%

GetHexData:	1485мс.
OpenHex:	906мс.
Разница: 	38.99%

GetHexData:	1438мс.
OpenHex:	891мс.
Разница: 	38.04%
-------------------------
-------------------------
-------------------------	Файл: 	Kub0 - In The Dark.mp3
-	CPU Eco:	-
GetHexData:	27656мс.
OpenHex:	19766мс.
Разница: 	28.53%

GetHexData:	27969мс.
OpenHex:	20438мс.
Разница: 	26.93%

GetHexData:	28500мс.
OpenHex:	19469мс.
Разница: 	31.69%
-------------------------
-	CPU Balance:	-
GetHexData:	14938мс.
OpenHex:	10687мс.
Разница: 	28.46%

GetHexData:	14938мс.
OpenHex:	10562мс.
Разница: 	29.29%

GetHexData:	14938мс.
OpenHex:	10593мс.
Разница: 	29.09%
-------------------------
-	CPU Max:	-
GetHexData:	11016мс.
OpenHex:	7937мс.
Разница: 	27.95%

GetHexData:	10953мс.
OpenHex:	7907мс.
Разница: 	27.81%

GetHexData:	10953мс.
OpenHex:	7969мс.
Разница: 	27.24%

-------------------------
-	CPU Balance:	-
GetHexData:	15062мс.
OpenHex:	10625мс.
Разница: 	29.46%

GetHexData:	14969мс.
OpenHex:	10641мс.
Разница: 	28.91%

GetHexData:	15375мс.
OpenHex:	10578мс.
Разница: 	31.2%
-------------------------
-	CPU Eco:	-
GetHexData:	27687мс.
OpenHex:	19938мс.
Разница: 	27.99%

GetHexData:	28781мс.
OpenHex:	19797мс.
Разница: 	31.22%

GetHexData:	28219мс.
OpenHex:	20063мс.
Разница: 	28.9%

GetHexData:	27547мс.
OpenHex:	19187мс.
Разница: 	30.35%
Win11x64, AHK v1.1.37.01 (Unicode 64-bit), AHK v2.0.17| AHK-Wiki | Переменные и выражения | RegEx101

2

Re: AHK: Извлечь Hex данные из файла

Ещё такой вариант протестируйте:

#SingleInstance Force
#MaxMem, 4095
#NoEnv
SetBatchLines -1
SetWorkingDir %A_ScriptDir%

File := "123.mp3"			; Размер файла:	1.87 Мб.
;File := "Kub0 - In The Dark.mp3"	; Размер файла:	10.1 Мб.

;-------------------------
ToolTip, [Обработка], 0, 0

TTime(0)	; Начать отсчёт времени.
A1 := GetHexData(File)
T1 := TTime(1)	; Завершить отсчёт.

TTime(0)
A2 := OpenHex(File)
T2 := TTime(1)

AA := ["Да", "Нет"][2 - (A1 = A2)]	; Проверка на совпадение 'Hex' данных.
P := Procent(T1, T2, 2, 1)		; Разница в процентах.

/*
; Для проверки - сохранить в файл Hex данные:
ToolTip, [Сохранение 1], 0, 0
WriteHex(A1, "Test A1.mp3")

ToolTip, [Сохранение 2], 0, 0
WriteHex(A2, "Test A2.mp3")
*/
ToolTip
MsgBox, % File "`n`nGetHexData:`t" T1 "мс.`nOpenHex:`t" T2 "мс.`n`nСовпало:`t" AA "`nРазница: `t" P
Return


;============================================================================================================================================

GetHexData(SourseFile){
    static fmt := CRYPT_STRING_HEXRAW := 0xC
    File := FileOpen(SourseFile, "r", "cp0")
    size := File.RawRead(bin, File.Length)
    if !DllCall("Crypt32\CryptBinaryToString", "Ptr", &bin, "UInt", size, "UInt", fmt, "Ptr", 0, "UIntP", chars)
        throw "CryptBinaryToString failed. LastError: " . A_LastError
    VarSetCapacity(outData, chars << !!A_IsUnicode)
    DllCall("Crypt32\CryptBinaryToString", "Ptr", &bin, "UInt", size, "UInt", fmt, "Str", outData, "UIntP", chars)
    return RTrim(outData, "`r`n")
}


OpenHex(File){ ;23:17 10.11.2024	Ускоренная версия:
 File := FileOpen(File, "r"), File.Pos := 0, File.RawRead(Buf, Length := File.Length), File.Close(), F := A_FormatInteger
 SetFormat, IntegerFast, Hex
 Loop % Length
  R := SubStr(NumGet(Buf, A_Index - 1, "UChar"), 3), Hex .= (StrLen(R) < 2 ? "0" R : R)
 SetFormat, IntegerFast, % F
 Return Hex
}

; 09:08 27.04.2022	Сохранить 'Hex' в файл.
WriteHex(HexStr, Path = "WriteHex.txt"){
 File := FileOpen(Path, "w")
 While(I := SubStr(HexStr, A_Index*2-1, 2)) != ""
  File.WriteUChar("0x" I)
 File.Close()
}

;23:29 03.01.2022	Для быстрого определения прошедшего времени для команд. Без ограничений для отсчёта разниц.
;M: 0:Начать отсчёт, 1:Вернуть разницу. I - индекс в массиве таймингов.
TTime(M := 1, I := 1){
 Static C := {}
 Return (M ? A_TickCount-C[i] : C[i] := A_TickCount)	; Сокращённый вариант.
}

;01:15 11.11.2024 Доработка: автоматически сравнивает меньшее от большего. Compare - отвечает за сравнение разницы чисел.
Procent(n1, n2, R := 2, Compare = 0){
 P := (Min(n1, n2) / Max(n1, n2)) * 100
 If (Compare)
  P := 100 - P
 Return ARound(P, R) "%"
}

; Округление числа до R знаков после запятой +удаление лишних нулей и точки, если она осталась.
ARound(N, R := 2){ ; N:Число, R:Округление после запятой.
 Return RTrim(RTrim(Round(N, R), "0"), ".")
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

3

Re: AHK: Извлечь Hex данные из файла

Потрясающая скорость! Я такого даже не ожидал.

CPU Max:	Kub0 - In The Dark.mp3
GetHexData:	875мс.
OpenHex:	8140мс.
Разница: 	89.25%
Win11x64, AHK v1.1.37.01 (Unicode 64-bit), AHK v2.0.17| AHK-Wiki | Переменные и выражения | RegEx101

4

Re: AHK: Извлечь Hex данные из файла

Ещё удалось ускорить функцию сохранения 'Hex' строки в файл (~46%):

WriteHex2(Hex_Str, File := "WriteHex2.txt"){	;02:16 13.11.2024 Сохранить 'Hex' строку бинарно в файл:
 DllCall("Crypt32\CryptStringToBinary", "Ptr", &Hex_Str, "UInt", StrLen(Hex_Str), "UInt", 0xC, "UInt", 0, "UIntP", bytes, "UIntP", 0, "UIntP", 0)
 VarSetCapacity(outData, bytes)
 DllCall("Crypt32\CryptStringToBinary", "Ptr", &Hex_Str, "UInt", StrLen(Hex_Str), "UInt", 0xC, Str, outData, "UIntP", bytes, "UIntP", 0, "UIntP", 0)
 File := FileOpen(File, "w"), File.RawWrite(outData, bytes), File.Close()
}
Win11x64, AHK v1.1.37.01 (Unicode 64-bit), AHK v2.0.17| AHK-Wiki | Переменные и выражения | RegEx101