Seite 1 von 2
Grösse eines Listenelementes ermitteln
Verfasst: 17.09.2019 17:32
von Kuno
Hallo kann mir jemand bei meinem Problem helfen
und zwar möchte ich die grösse eines Listenelementes ermitteln um es dann zu speichern ,aber wie.
Habe schon im Forum ge googelt aber nichts passendes gefunden.
Hier mal mein bisheriger Code :
Code: Alles auswählen
Structure fmpro
form.b
zeit.d
meldung.s
EndStructure
Global NewList FMProt.fmpro()
AddElement(FMProt())
FMProt()\form = 1
FMProt()\zeit=1444255255252
FMProt()\meldung="hallaoaoaoaoaoao"
AddElement(FMProt())
FMProt()\form = 2
FMProt()\zeit=144
FMProt()\meldung="hallaoaoa htuuutaoaoaoao"
If CreateFile(0, "Text.prot")
ForEach FMProt()
*Element.fmpro = @FMProt()
size = MemorySize(*Element)
WriteData(MyFileHandle, @FMProt(),size ) ; SizeOf(fmpro))
Next
EndIf
speziell die Zeile mit ' size = MemorySize(*Element) ' funktioniert nicht so wie ich dachte.
Vielleicht kann mir jemand helfen, ich weiss nicht mehr weiter.
Re: Grösse eines Listenelementes ermitteln
Verfasst: 17.09.2019 17:52
von Bisonte
Das wird so nicht wirklich klappen.
Der grosse Problempunkt ist der String in deiner Struktur.
Es ist eigentlich gar nicht der String in FMProt()\meldung,
sondern nur der Pointer, der auf die Speicheradresse zeigt,
wo der String gespeichert ist.
Am besten kann man solche Speicherungen mit JSON erledigen.
Dazu weiteres in der Hilfe nachlesen (F1).
Hier verwende ich einfach mal deinen "Prototyp" um ihn als Datei zu speichern....
egal wieviele Einträge vorhanden sind :
Code: Alles auswählen
Structure fmpro
form.b
zeit.d
meldung.s
EndStructure
Global NewList FMProt.fmpro()
AddElement(FMProt())
FMProt()\form = 1
FMProt()\zeit=1444255255252
FMProt()\meldung="hallaoaoaoaoaoao"
AddElement(FMProt())
FMProt()\form = 2
FMProt()\zeit=144
FMProt()\meldung="hallaoaoa htuuutaoaoaoao"
; Json erstellen
jSon = CreateJSON(#PB_Any, #PB_JSON_NoCase)
If jSon
; Liste einfügen
InsertJSONList(JSONValue(jSon), FMProt())
; Json speichern
If Not SaveJSON(jSon, "Text.json", #PB_JSON_PrettyPrint)
Debug "Fehler beim Speichern"
EndIf
; Json freigeben
FreeJSON(jSon)
EndIf
Jetzt kannst du dir die datei mit einem Texteditor ansehen...
Re: Grösse eines Listenelementes ermitteln
Verfasst: 17.09.2019 17:53
von NicTheQuick
Hey McKay!
So einfach funktioniert das leider nicht, wenn Strings im Spiel sind.
Normalerweise würde man SizeOf(fmpro) nutzen um die Strukturgröße zu ermitteln, denn Strukturen sind erst mal immer statisch und gleich groß. Strings in Strukturen sind nichts anderes als Pointer zum eigentlichen String. Das heißt egal wie lange der String ist, den du in deinem strukturierten Element speicherst, das Element selbst bleibt gleich groß. Allerdings zeigt das String-Feld (in deinem Fall 'meldung.s') zum eigentlich String im Speicher.
Der Einfachheit halbe würde ich jedes Strukturelement einzeln schreiben:
Code: Alles auswählen
Structure fmpro
form.b
zeit.d
meldung.s
EndStructure
Global NewList FMProt.fmpro()
AddElement(FMProt())
FMProt()\form = 1
FMProt()\zeit=1444255255252
FMProt()\meldung="hallaoaoaoaoaoao"
AddElement(FMProt())
FMProt()\form = 2
FMProt()\zeit=144
FMProt()\meldung="hallaoaoa htuuutaoaoaoao"
If CreateFile(0, "Text.prot")
ForEach FMProt()
*Element.fmpro = @FMProt()
WriteByte(MyFileHandle, *Element\form)
WriteDouble(MyFileHandle, *Element\zeit)
; Jetzt meldung
WriteString(MyFileHandle, *Element\meldung)
; und Nullterminierung
WriteByte(MyFileHandle, 0)
Next
EndIf
Re: Grösse eines Listenelementes ermitteln
Verfasst: 17.09.2019 18:04
von Josh
NicTheQuick hat geschrieben:Code: Alles auswählen
ForEach FMProt()
*Element.fmpro = @FMProt()
WriteByte(MyFileHandle, *Element\form)
WriteDouble(MyFileHandle, *Element\zeit)
; Jetzt meldung
WriteString(MyFileHandle, *Element\meldung)
; und Nullterminierung
WriteCharacter(MyFileHandle, 0) <-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Next
Unbedingt ein WriteCharacter anstatt WriteByte verwenden. Zusätzlich würde ich als erstes Element in der Datei die Anzahl der Listeinträge in einem Long speichern. Beim Auslesen liest du dann als erster die Anzahl der Listeinträge und durchläufst dann eine For-Schleife.
Bisonte hat geschrieben:Am besten kann man solche Speicherungen mit JSON erledigen.
Auf JSON würde ich an deiner Stelle verzichten. Das ist in jeder Beziehung der absolute Killer.
Re: Grösse eines Listenelementes ermitteln
Verfasst: 17.09.2019 18:39
von NicTheQuick
Josh hat geschrieben:Unbedingt ein WriteCharacter anstatt WriteByte verwenden. Zusätzlich würde ich als erstes Element in der Datei die Anzahl der Listeinträge in einem Long speichern. Beim Auslesen liest du dann als erster die Anzahl der Listeinträge und durchläufst dann eine For-Schleife.
Sicher? Da WriteString() standardmäßig als UTF-8 schreibt, sollte ein Nullbyte reichen. Zwei wären eines zu viel.
Re: Grösse eines Listenelementes ermitteln
Verfasst: 17.09.2019 19:03
von Josh
NicTheQuick hat geschrieben:Sicher? Da WriteString() standardmäßig als UTF-8 schreibt, sollte ein Nullbyte reichen. Zwei wären eines zu viel.
Nein, nicht sicher. Eher sicher, dass ich da falsch gelegen bin
Jetzt muss ich bei mir im Code mal gucken, wie ich das gemacht habe.
Re: Grösse eines Listenelementes ermitteln
Verfasst: 17.09.2019 19:28
von mk-soft
Ich will auch
I like XML
Code: Alles auswählen
Structure fmpro
form.b
zeit.d
meldung.s
EndStructure
Procedure LoadProtocolData(Path.s, List Protocol.fmpro())
Protected filename.s, xml
filename = Path + "ProtocolData.xml"
If FileSize(filename) > 0
xml = LoadXML(#PB_Any, filename)
If xml And XMLStatus(xml) = #PB_XML_Success
ExtractXMLList(MainXMLNode(xml), Protocol(), #PB_XML_NoCase)
FreeXML(xml)
EndIf
EndIf
EndProcedure
; ----
Procedure SaveProtocolData(Path.s, List Protocol.fmpro())
Protected filename.s, xml
filename = Path + "ProtocolData.xml"
xml = CreateXML(#PB_Any)
If xml
If InsertXMLList(RootXMLNode(xml), Protocol())
FormatXML(xml, #PB_XML_ReFormat)
SaveXML(xml, filename)
EndIf
EndIf
EndProcedure
; ----
Global NewList FMProt.fmpro()
AddElement(FMProt())
FMProt()\form = 1
FMProt()\zeit=1444255255252
FMProt()\meldung="hallaoaoaoaoaoao"
AddElement(FMProt())
FMProt()\form = 2
FMProt()\zeit=144
FMProt()\meldung="hallaoaoa htuuutaoaoaoao"
path.s = GetUserDirectory(#PB_Directory_Documents)
SaveProtocolData(path, FMProt())
CallDebugger
LoadProtocolData(path, FMProt())
CallDebugger
Re: Grösse eines Listenelementes ermitteln
Verfasst: 17.09.2019 20:16
von HeX0R
Ich würde es wie Bisonte machen!
Keine Ahnung was die Bemerkung von Josh bedeuten soll.
Re: Grösse eines Listenelementes ermitteln
Verfasst: 17.09.2019 20:24
von Josh
Josh hat geschrieben:Jetzt muss ich bei mir im Code mal gucken, wie ich das gemacht habe.
Ja, hab bei mir auch
WriteByte verwendet. Na hab zumindest hab ich für ein wenig Verwirrung in einem langweiligen Thread gesorgt
mk-soft hat geschrieben:Ich will auch
I like XML
Ich hab zwar mit XML noch nicht herumexperimentiert, aber kann mir gut vorstellen, dass das genau so ein Performancekiller wie JSON ist.
HeX0R hat geschrieben:Keine Ahnung was die Bemerkung von Josh bedeuten soll.
JSON ist ja vielleicht gut geeignet, Daten zwischen zwei Programmen auszutauschen. Kann auch gut dazu geeignet sein, wenn dein Anwender zwischendurch gerne mal eine Zigarette raucht oder einen Kaffee trinkt. Ich hatte mal herumexperimentiert und bin auf einen zeitlichen Faktor von 70 bis 100 gegenüber dem System von
NicTheQuick gekommen. Die aufgeblähten Dateien spielen zwar heute kaum mehr eine Rolle, sind aber trotzdem unnötig.
Re: Grösse eines Listenelementes ermitteln
Verfasst: 17.09.2019 20:58
von HeX0R
Es war hier nicht nach einer besonders performanten Lösung gefragt.
Und wenn es ums Laden und Speichern von Maps oder Listen geht, gibt's nix einfacheres, die XML Lösung ist natürlich vergleichbar, aber XML erzeugt m. E. zuviel Overhead.
Du brauchst dich um nix zu kümmern, musst deinen Code auch nicht anpassen, wenn Du die Struktur der Liste/Map änderst.
Klar, wenn es sauschnell sein muss, würde ich das auch nicht nutzen, aber das steht hier nirgends.
[Edit]
Als "Killer" würde ich es auch nicht bezeichnen.
Ich habe ein Projekt mit einer Map bestehend aus ca. 3000 Modbus Registern, inkl. jeweils Register, Typ, Name, Beschreibung, noch nen paar Flags. Habe noch nie die Zeit beim Laden und Speichern gestoppt, aber gefühlt bin ich bei etwa einer Sekunde.