Grösse eines Listenelementes ermitteln

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Kuno
Beiträge: 3
Registriert: 30.10.2010 19:27

Grösse eines Listenelementes ermitteln

Beitrag 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.
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

Re: Grösse eines Listenelementes ermitteln

Beitrag 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...
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Grösse eines Listenelementes ermitteln

Beitrag 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
Bild
Benutzeravatar
Josh
Beiträge: 1028
Registriert: 04.08.2009 17:24

Re: Grösse eines Listenelementes ermitteln

Beitrag 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.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Grösse eines Listenelementes ermitteln

Beitrag 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.
Bild
Benutzeravatar
Josh
Beiträge: 1028
Registriert: 04.08.2009 17:24

Re: Grösse eines Listenelementes ermitteln

Beitrag 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 :oops:
Jetzt muss ich bei mir im Code mal gucken, wie ich das gemacht habe.
Benutzeravatar
mk-soft
Beiträge: 3695
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Grösse eines Listenelementes ermitteln

Beitrag von mk-soft »

Ich will auch :mrgreen:

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
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
HeX0R
Beiträge: 2954
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win10 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2
Kontaktdaten:

Re: Grösse eines Listenelementes ermitteln

Beitrag von HeX0R »

Ich würde es wie Bisonte machen!
Keine Ahnung was die Bemerkung von Josh bedeuten soll.
Benutzeravatar
Josh
Beiträge: 1028
Registriert: 04.08.2009 17:24

Re: Grösse eines Listenelementes ermitteln

Beitrag 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 :mrgreen:

mk-soft hat geschrieben:Ich will auch :mrgreen:
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.
Benutzeravatar
HeX0R
Beiträge: 2954
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win10 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2
Kontaktdaten:

Re: Grösse eines Listenelementes ermitteln

Beitrag 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.
Antworten