Тема: AHK: Сохранение массива в строку
Если требуется сохранить массив, например по завершении работы сохранить в ключ ини файла или текстовый файл, а при старте скрипта восстановить массив, то используя приведённые функции можно перевести массив в строку и обратно.
Оригинал здесь, я посчитал удобным адаптировать его для использования с Base64.
ObjToBase64 - передаём массив, получаем строку.
ObjFromBase64 - передаём строку, получаем массив.
Также есть пример сравнения массивов.
----------------------------------------------
----------------------------------------------
Функции: (правка: 10:37 16.11.2017)
ObjToBase64(obj) {
If !IsObject(obj)
Return
VarSetCapacity(Bin, Size := RawObjectSize(obj, 0) + 8, 0)
RawObject(obj, NumPut(Size - 8, 0 + (addr := &Bin), "Int64"), 0)
DllCall("Crypt32.dll\CryptBinaryToString"
, Ptr, addr, UInt, Size, UInt, 0x00000001|0x40000000, UInt, 0, UIntP, TChars, "CDECL Int")
VarSetCapacity(Base64, Req := TChars * (A_IsUnicode ? 2 : 1 ))
DllCall("Crypt32.dll\CryptBinaryToString"
, Ptr, addr, UInt, Size, UInt, 0x00000001|0x40000000, Str, Base64, UIntP, Req, "CDECL Int")
Return Base64
}
ObjFromBase64(Base64) {
DllCall("Crypt32.dll\CryptStringToBinary", Ptr, &Base64
, UInt, StrLen(Base64), UInt, 1, UInt, 0, UIntP, Bytes, Int, 0, Int, 0, "CDECL Int")
VarSetCapacity(OutData, Req := Bytes * (A_IsUnicode ? 2 : 1))
DllCall("Crypt32.dll\CryptStringToBinary", Ptr, &Base64
, UInt, StrLen(Base64), UInt, 1, Str, OutData, UIntP, Req, Int, 0, Int, 0, "CDECL Int")
Return ObjLoad(&OutData)
}
RawObject(obj, addr, buf := 0, objects := 0) {
; Type.Enum: Char.1 UChar.2 Short.3 UShort.4 Int.5 UInt.6 Int64.7 UInt64.8 Double.9 String.10 Object.11
; Negative for keys and positive for values
If !objects
objects:={(""):0,(obj):0}
Else
objects[obj]:=(++objects[""])
for k, v in obj
{ ; 9 = Int64 for size and Char for type
If IsObject(k) {
If objects.HasKey(k)
NumPut(-12,addr+0,"Char"),NumPut(objects[k],addr+1,"Int64"),addr+=9
Else
NumPut(-11,addr+0,"Char"),NumPut(sz:=RawObjectSize(k,buf),addr+1,"Int64"),RawObject(k,addr+9,buf,objects),addr+=sz+9
} Else
NumPut(-10,addr+0,"Char"),NumPut(sz:=StrPut(k,addr+9)*2,addr+1,"Int64"),addr+=sz+9
If IsObject(v) {
If objects.HasKey(v)
NumPut(12,addr+0,"Char"),NumPut(objects[v],addr+1,"Int64"),addr+=9
Else
NumPut(11,addr+0,"Char"),NumPut(sz:=RawObjectSize(v,buf),addr+1,"Int64"),RawObject(v,addr+9,buf,objects),addr+=sz+9
} Else
NumPut(10,addr+0,"Char"),NumPut(sz:=buf?obj.GetCapacity(k):StrPut(v)*2,addr+1,"Int64"),DllCall("RtlMoveMemory","PTR",addr+9,"PTR",buf?obj.GetAddress(k):&v,"PTR",sz),addr+=sz+9
}
}
RawObjectSize(obj,buf:=0,objects:=0){
If !objects
objects:={(obj):1}
Else If !objects.HasKey(obj)
objects[obj]:=1
for k, v in obj
{
If IsObject(k)
sz+=objects.HasKey(k)?9:RawObjectSize(k,buf,objects)+9
Else
sz+=StrPut(k)*2+9
If IsObject(v)
sz+=objects.HasKey(v)?9:RawObjectSize(v,buf,objects)+9
Else
sz+=(buf?obj.GetCapacity(k):StrPut(v)*2)+9
}
Return sz
}
ObjLoad(addr, objects := 0) {
obj:=[],end:=addr+8+(sz:=NumGet(addr+0,"Int64")),addr+=8
If !objects
objects:={0:obj}
Else
objects.Push(obj)
While addr < end { ; 9 = Int64 for size and Char for type
If NumGet(addr+0,"Char")=-12
k:=objects[NumGet(addr+1,"Int64")],addr+=9
Else If NumGet(addr+0,"Char")=-11
k:=ObjLoad(addr+1,objects),addr+=9+NumGet(addr+1,"Int64")
Else If NumGet(addr+0,"Char")=-10
sz:=NumGet(addr+1,"Int64"),k:=StrGet(addr+9),addr+=sz+9
Else
k:=NumGet(addr+1,SubStr("Char UChar Short UShortInt UInt Int64 UInt64Double",(sz:=-NumGet(addr+0,"Char"))*6-5,6)),addr+=SubStr("112244888",sz,1)+1
If NumGet(addr+0,"Char")= 12
obj[k]:=objects[NumGet(addr+1,"Int64")],addr+=9
Else If NumGet(addr+0,"Char")= 11
obj[k]:=ObjLoad(addr+1,objects),addr+=9+NumGet(addr+1,"Int64")
Else If NumGet(addr+0,"Char")= 10 {
If (k + 0 != "") && !(k ~="S)\s") && (abs(k) <= 2147483647)
obj[k]:=StrGet(addr+9),obj.SetCapacity(k,sz:=NumGet(addr+1,"Int64")),DllCall("RtlMoveMemory","PTR",obj.GetAddress(k),"PTR",addr+9,"PTR",sz),addr+=sz+9
Else
obj["" k]:=StrGet(addr+9),obj.SetCapacity("" k,sz:=NumGet(addr+1,"Int64")),DllCall("RtlMoveMemory","PTR",obj.GetAddress("" k),"PTR",addr+9,"PTR",sz),addr+=sz+9
} Else
obj[k]:=NumGet(addr+1,SubStr("Char UChar Short UShortInt UInt Int64 UInt64Double",(sz:=NumGet(addr+0,"Char"))*6-5,6)),addr+=SubStr("112244888",sz,1)+1
}
Return obj
}
#SingleInstance Force
#NoEnv
Arr := {"1key":{2key:[,,"value"]}}
Base64 := ObjToBase64(Arr)
MsgBox % Base64
Obj := ObjFromBase64(Base64)
MsgBox % Obj.1key.2key[3]
Prefix := {"LAlt":"<!","LCtrl":"<^","LShift":"<+","LWin":"<#"}
Base64 := ObjToBase64(Prefix)
MsgBox % Base64
Obj := ObjFromBase64(Base64)
for k, v in Obj
MsgBox % k " : " v
B := ["Ivan", 345, "London"]
Base64 := ObjToBase64(B)
MsgBox % Base64
Obj := ObjFromBase64(Base64)
for k, v in Obj
MsgBox % k " : " v
#SingleInstance Force
#NoEnv
MyClass := new Class
Loop 9
{
MyClass["v" A_Index] := A_Sec " . " A_Msec
Sleep 10
}
MyClass.a := {b:{c:"вложенный массив"}}
Base64 := ObjToBase64(MyClass)
MsgBox % Base64
NewObj := new Class
NewObj.Load(ObjFromBase64(Base64))
for k, v in NewObj, list := ""
list .= k " : " (IsObject(v) ? "IsObject" : v) "`n"
MsgBox % list
NewObj.Test()
Return
class Class {
x := 10, y := 20
Load(Obj) {
for k, v in Obj
This[k] := v
}
Test() {
MsgBox % this.a.b.c
}
}
#SingleInstance Force
#NoEnv
Base64 = /AEAAAAAAAD2BAAAAAAAAABhAAAAC04AAAAAAAAA9gQAAAAAAAAAYgAAAAs4AAAAAAAAAPYEAAAAAAAAAGMAAAAKIgAAAAAAAAAyBDsEPgQ2BDUEPQQ9BEsEOQQgADwEMARBBEEEOAQyBAAA9gYAAAAAAAAAdgAxAAAAChIAAAAAAAAAMAA3ACAALgAgADMAOAAwAAAA9gYAAAAAAAAAdgAyAAAAChIAAAAAAAAAMAA3ACAALgAgADMAOQA1AAAA9gYAAAAAAAAAdgAzAAAAChIAAAAAAAAAMAA3ACAALgAgADQAMAA1AAAA9gYAAAAAAAAAdgA0AAAAChIAAAAAAAAAMAA3ACAALgAgADQAMgA1AAAA9gYAAAAAAAAAdgA1AAAAChIAAAAAAAAAMAA3ACAALgAgADQANAA1AAAA9gYAAAAAAAAAdgA2AAAAChIAAAAAAAAAMAA3ACAALgAgADQANQA0AAAA9gYAAAAAAAAAdgA3AAAAChIAAAAAAAAAMAA3ACAALgAgADQANwAyAAAA9gYAAAAAAAAAdgA4AAAAChIAAAAAAAAAMAA3ACAALgAgADQAOAA0AAAA9gYAAAAAAAAAdgA5AAAAChIAAAAAAAAAMAA3ACAALgAgADUAMAA0AAAA9gQAAAAAAAAAeAAAAAIK9gQAAAAAAAAAeQAAAAIU
NewObj := new Class
NewObj.Load(ObjFromBase64(Base64))
NewObj.Test()
for k, v in NewObj, list := ""
list .= k " : " (IsObject(v) ? "IsObject" : v) "`n"
MsgBox % list
Return
class Class {
Load(Obj) {
for k, v in Obj
This[k] := v
}
Test() {
MsgBox % this.a.b.c
}
}
Win10x64 AhkSpy, Hotkey, ClockGui