Objekte als Datei speichern

Post a reply


In an effort to prevent automatic submissions, we require that you complete the following challenge.
Smilies
:D :) ;) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :!: :?: :idea: :| :mrgreen: :geek: :ugeek: :arrow: :angel: :clap: :crazy: :eh: :lolno: :problem: :shh: :shifty: :sick: :silent: :think: :thumbup: :thumbdown: :salute: :wave: :wtf: :yawn: :facepalm: :bravo: :dance: :beard: :morebeard: :xmas: :HeHe: :trollface: :cookie: :rainbow: :monkeysee: :monkeysay: :happybday: :headwall: :offtopic: :superhappy: :terms: :beer:
View more smilies

BBCode is ON
[img] is OFF
[flash] is OFF
[url] is ON
Smilies are ON

Topic review
   

Expand view Topic review: Objekte als Datei speichern

Re: Objekte als Datei speichern

Post by bichlepa » 10 Mar 2015, 10:51

Ich habe es mit dem Skript von LearningOne geschafft. :D
Ich habe den Skript auch so umgestaltet, dass jede globale Variable in AutoHotFlow in eine separate Datei geschrieben wird.

Trotzdem vielen Dank, nnnik, für deine Hilfe!

Re: Objekte als Datei speichern

Post by bichlepa » 10 Mar 2015, 04:08

Ich habe gerade beim Googeln nach "ObjToStr ahk" den Skript von LearningOne gefunden: http://www.autohotkey.com/board/topic/6 ... tructures/
Ich experimentiere gerade damit herum. Es scheint zu funktionieren und bietet zudem den Vorteil, dass die entstandenen Dateien sehr gut "human-readable" sind. Ich sage dann bescheid, ob es funktioniert. Es gibt aber noch einige Probleme im eigenen Code zu beseitigen.

Re: Objekte als Datei speichern

Post by nnnik » 10 Mar 2015, 03:59

Oder vielleicht ein Array aus Objekten zu speichern?
Hmm.. Ich könnte schwören, dass es gestern noch funktioniert hat.

Re: Objekte als Datei speichern

Post by bichlepa » 10 Mar 2015, 03:05

Danke! Das ist ein vielversprechender Skript! Genau das, was ich gesucht habe! :D
Ich habe den mal ausprobiert. Es funktioniert aber nicht ganz. :( Bei eindimensionalen Arrays funktioniert es, aber bei mehrdimensionalen Arrays kommt es durcheinander.
Beispiel:

Code: Select all


D:=[{a:1,b:2,c:3},{a:2,b:3,c:1},{a:3,b:1,c:2}]
Msgbox % D[1]["c"] . ", " . D[2,"b"] . ", " . D[3,"a"] ;Ausgabe: 3, 3, 3
ObjToFile(D,"Test.dat")
F:=ObjFromFile("Test.dat")
Msgbox % F[1]["c"] . ", " . F[2,"b"] . ", " . F[3,"a"] ;Ausgabe: , ,

D:=["a","b", ["c","d"], "e"]
Msgbox % D[1] . ", " . D[2] . ", " . D[3][1] . ", " . D[3][2] . ", " . D[4] ;Ausgabe: a, b, c, d, e
ObjToFile(D,"Test.dat")
F:=ObjFromFile("Test.dat")
Msgbox % F[1] . ", " . F[2] . ", " . F[3][1] . ", " . F[3][2] . ", " . F[4] ;Ausgabe: a, b, c, d㐀, 

ObjToFile(Obj,Filename)
{
    Length:=ObjToBinary(Obj)
    VarSetCapacity(Bin,Length,0)
    ObjToBinary(Obj,&Bin)
    
    File:=FileOpen(Filename,"w")
    File.RawWrite(Bin,Length)
    File.Close()

    Return Length
}

ObjFromFile(Filename)
{
    
    File:=FileOpen(Filename,"r")
    File.RawRead(Bin,File.Length)
    File.Close()

    Return ObjFromBinary(&Bin)
}

ObjToBinary(Obj,Ptr=0)
{
    Len:=4
    Nr:=0
    Arr:=[]
    For Key, Value in Obj
    {
        Nr++
        Len+=StrPut(Key,"UTF-16")*2
        If (Value|0=="")
        {
            If IsObject(Value)
            {
                TypeNr:=3
                Len+=StrPut(GetClassName(Value),"UTF-16")*2
                Len+=ObjToBinary(Value)
            }
            Else
            {
                TypeNr:=0
                Len+=StrPut(Value,"UTF-16")*2
            }
        }
        Else
        {
            TypeNr:=1+!(InStr(Value,"."))
            Len+=8
        }
        Arr.Insert({Key:Key,Value:Value,TypeNr:TypeNr})
    }
    If !Ptr
        Return Len
    Ptr1:=Ptr+4
    Ptr2:=Ptr+Ceil(Nr/4)+4
    NumPut(Nr,(Ptr+0),"UInt")
    B:=C:=0
    For Index,KeyValue in Arr
    {
        B:=(B<<2)|KeyValue.TypeNr
        C++
        If (C=4)
        {
            NumPut(B,(Ptr1+0),"UChar")
            C:=B:=0
            Ptr+=1
        }
        Ptr2+=StrPut(KeyValue.Key,Ptr2,"UTF-16")*2
        If !KeyValue.TypeNr
            Ptr2+=StrPut(KeyValue.Value,Ptr2,"UTF-16")*2
        Else If (KeyValue.TypeNr<3)
        {
            NumPut(KeyValue.Value,(Ptr2+0),(KeyValue.TypeNr-1)?"Double":"Int64")
            Ptr2+=8
        }
        Else
        {
            Ptr2+=StrPut(GetClassName(KeyValue.Value),Ptr2,"UTF-16")*2
            Ptr2+=ObjToBinary(KeyValue.Value,Ptr2)
        }
    }
    Return Len
}

ObjFromBinary(Ptr,Obj="")
{
    If !Ptr
        Return
    If !IsObject(Obj)
        Obj:={}
    Ptr1:=Ptr
    Nr:=NumGet(Ptr1+0,"UInt")
    Ptr2:=(Ptr1+=4)+Ceil(Nr/16)
    C:=0
    Loop % Nr
    {
        C--
        If (C<0)
        {
            B:=NumGet(Ptr1+0,"UChar")
            Ptr+=1
            C:=4
        }
        TypeNr:=(B&0xC0)>>6
        B<<=2
        Key:=StrGet(Ptr2+0,"UTF-16")
        Ptr2+=StrPut(Key,"UTF-16")*2
        If (TypeNr=3)
        {
            ValueClass:=StrGet(Ptr2+0,"UTF-16")
            Ptr2+=StrPut(ValueClass,"UTF-16")*2
            If (ValueClass)
                Obj[Key]:=New %ValueClass%()
            Else
                Obj[Key]:={}
            Ptr2+=ObjFromBinary(Ptr2,Obj[Key])
        }
        Else If (TypeNr=1)
        {
            Obj[Key]:=NumGet(Ptr2+0,"Double")
            Ptr2+=8
        }
        Else If (TypeNr=2)
        {
            Obj[Key]:=NumGet(Ptr2+0,"Int64")
            Ptr2+=8
        }
        Else
        {
            Obj[Key]:=StrGet(Ptr2+0,"UTF-16")
            Ptr2+=StrPut(Obj[Key],"UTF-16")*2
        }
    }
    Return Obj
}

GetClassName(C)
{
    While (IsObject(C:=C.base)&&!C.HasKey("__Class"))
        Continue
    Return C.__Class
}
Ich habe es mit der Aktuellen AHK Version v1.1.20.00 probiert
nnnik wrote:Ich verstehe auch nicht wieso du 2 verschiedene Parser (ini und objekt) verwenden willst.
Vielleicht habe ich mich etwas missverständlich ausgedrückt. Meine Idee war, beim Speichern des Objekts das Objekt zu einem String zu machen und als ein Eintrag in eine .ini zu schreiben und beim Laden andersherum. So könnte ich mehrere Objekte in einer .ini Datei schreiben. Die Alternative zu ini ist, für jedes Objekt jeweils eine Datei zu verwenden.

Re: Objekte als Datei speichern

Post by nnnik » 09 Mar 2015, 17:59

Also von der Performance musst du dir keine Gedanken machen.
Ich verstehe auch nicht wieso du 2 verschiedene Parser (ini und objekt) verwenden willst.

Code: Select all

D:=[{a:1,b:2,c:3},{a:2,b:3,c:1},{a:3,b:1,c:2}]
ObjToFile(D,"Test.dat")
F:=ObjFromFile("Test.dat")
Msgbox % F[1,"c"] . ", " . F[2,"b"] . ", " . F[3,"a"]

ObjToFile(Obj,Filename)
{
	Length:=ObjToBinary(Obj)
	VarSetCapacity(Bin,Length,0)
	ObjToBinary(Obj,&Bin)
	
	File:=FileOpen(Filename,"w")
	File.RawWrite(Bin,Length)
	File.Close()

	Return Length
}

ObjFromFile(Filename)
{
	
	File:=FileOpen(Filename,"r")
	File.RawRead(Bin,File.Length)
	File.Close()

	Return ObjFromBinary(&Bin)
}

ObjToBinary(Obj,Ptr=0)
{
	Len:=4
	Nr:=0
	Arr:=[]
	For Key, Value in Obj
	{
		Nr++
		Len+=StrPut(Key,"UTF-16")*2
		If (Value|0=="")
		{
			If IsObject(Value)
			{
				TypeNr:=3
				Len+=StrPut(GetClassName(Value),"UTF-16")*2
				Len+=ObjToBinary(Value)
			}
			Else
			{
				TypeNr:=0
				Len+=StrPut(Value,"UTF-16")*2
			}
		}
		Else
		{
			TypeNr:=1+!(InStr(Value,"."))
			Len+=8
		}
		Arr.Insert({Key:Key,Value:Value,TypeNr:TypeNr})
	}
	If !Ptr
		Return Len
	Ptr1:=Ptr+4
	Ptr2:=Ptr+Ceil(Nr/4)+4
	NumPut(Nr,(Ptr+0),"UInt")
	B:=C:=0
	For Index,KeyValue in Arr
	{
		B:=(B<<2)|KeyValue.TypeNr
		C++
		If (C=4)
		{
			NumPut(B,(Ptr1+0),"UChar")
			C:=B:=0
			Ptr+=1
		}
		Ptr2+=StrPut(KeyValue.Key,Ptr2,"UTF-16")*2
		If !KeyValue.TypeNr
			Ptr2+=StrPut(KeyValue.Value,Ptr2,"UTF-16")*2
		Else If (KeyValue.TypeNr<3)
		{
			NumPut(KeyValue.Value,(Ptr2+0),(KeyValue.TypeNr-1)?"Double":"Int64")
			Ptr2+=8
		}
		Else
		{
			Ptr2+=StrPut(GetClassName(KeyValue.Value),Ptr2,"UTF-16")*2
			Ptr2+=ObjToBinary(KeyValue.Value,Ptr2)
		}
	}
	Return Len
}

ObjFromBinary(Ptr,Obj="")
{
	If !Ptr
		Return
	If !IsObject(Obj)
		Obj:={}
	Ptr1:=Ptr
	Nr:=NumGet(Ptr1+0,"UInt")
	Ptr2:=(Ptr1+=4)+Ceil(Nr/16)
	C:=0
	Loop % Nr
	{
		C--
		If (C<0)
		{
			B:=NumGet(Ptr1+0,"UChar")
			Ptr+=1
			C:=4
		}
		TypeNr:=(B&0xC0)>>6
		B<<=2
		Key:=StrGet(Ptr2+0,"UTF-16")
		Ptr2+=StrPut(Key,"UTF-16")*2
		If (TypeNr=3)
		{
			ValueClass:=StrGet(Ptr2+0,"UTF-16")
			Ptr2+=StrPut(ValueClass,"UTF-16")*2
			If (ValueClass)
				Obj[Key]:=New %ValueClass%()
			Else
				Obj[Key]:={}
			Ptr2+=ObjFromBinary(Ptr2,Obj[Key])
		}
		Else If (TypeNr=1)
		{
			Obj[Key]:=NumGet(Ptr2+0,"Double")
			Ptr2+=8
		}
		Else If (TypeNr=2)
		{
			Obj[Key]:=NumGet(Ptr2+0,"Int64")
			Ptr2+=8
		}
		Else
		{
			Obj[Key]:=StrGet(Ptr2+0,"UTF-16")
			Ptr2+=StrPut(Obj[Key],"UTF-16")*2
		}
	}
	Return Obj
}

GetClassName(C)
{
	While (IsObject(C:=C.base)&&!C.HasKey("__Class"))
		Continue
	Return C.__Class
}

Objekte als Datei speichern

Post by bichlepa » 09 Mar 2015, 16:23

Ich möchte für AutoHotFlow Objekte, die verschiedene Keys und Values haben, entweder als Datei oder als Eintrag in einer .ini Datei speichern. Das wird in AutoHotFlow für das Speichern von Listen als globale Variablen benötigt. Die Keys können entweder Nummern (wie in einem Array) oder alphanumerische Bezeichnungen sein.

Ich habe mir überlegt, alle Inhalte in einen speziell formatierten String zu speichern, den ich dann als ein Eintrag in eine .ini Datei schreiben kann. Beim Laden müsste ich diesen String parsen und das Objekt basteln. Damit wäre aber ein fehlerträchtiger und eventuell nicht sehr performanter Entwicklungsaufwand nötig. Daher frage ich, ob es auch einfacher geht.

Top