Problem mit WriteFile/Speichern

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

 

Lador

Betreff: Problem mit WriteFile/Speichern

BeitragMi, Nov 04, 2009 22:33
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo Community.

Ich habe in den letzten Wochen zwei verschiedene Editoren für mein Spiel "Iliran" programmiert. Diese sollten mir das Setzen von NPCs/Gegnern bzw. von Items/Zaubern erleichtern. Die funktionieren auch ganz gut, es gibt nur ein Problem mit dem Speichern. Zuerst nur beim NPC-Editor, und komischerweise jetzt auch beim Item-Editor.

Zum Speichern habe ich jeweils .txt-Dateien mit WriteFile() angelegt. Alle NPCs, Gegner und Gegner-Typen sollten jeweils in die Dateien "NPCs.txt", "Gegner.txt" bzw. "Gegner-Typ.txt" gespeichert werden. Das sieht so aus:

Code: [AUSKLAPPEN]

Function Speichern()
   Local Datei:TStream
   Datei = WriteFile("NPCs.txt")
   For Local TempNPC:TCharakter = EachIn NPCList
      WriteLine Datei, TempNPC.ID
      WriteLine Datei, TempNPC.Typ
      WriteLine Datei, TempNPC.Name
      WriteLine Datei, TempNPC.Gruppe
      WriteLine Datei, TempNPC.px
      WriteLine Datei, TempNPC.py
      WriteLine Datei, TempNPC.x1
      WriteLine Datei, TempNPC.x2
      WriteLine Datei, TempNPC.y1
      WriteLine Datei, TempNPC.y2
      WriteLine Datei, TempNPC.SFrame
      WriteLine Datei, TempNPC.Geschwindigkeit
      WriteLine Datei, TempNPC.MapName
      WriteLine Datei, ""
   Next
   CloseFile Datei
   Datei = WriteFile("Gegner.txt")
   For Local TempGegner:TGegner = EachIn GegnerList
      WriteLine Datei, TempGegner.ID
      WriteLine Datei, TempGegner.Typ
      WriteLine Datei, TempGegner.Gruppe
      WriteLine Datei, TempGegner.px
      WriteLine Datei, TempGegner.py
      WriteLine Datei, TempGegner.x1
      WriteLine Datei, TempGegner.x2
      WriteLine Datei, TempGegner.y1
      WriteLine Datei, TempGegner.y2
      WriteLine Datei, TempGegner.Geschwindigkeit
      WriteLine Datei, TempGegner.MapName
      WriteLine Datei, ""
   Next
   CloseFile Datei
   Datei = WriteFile("GegnerTyp.txt")
   For Local TempGegnerTyp:TGegnerTyp = EachIn GegnerTypList
      WriteLine Datei, TempGegnerTyp.ID
      WriteLine Datei, TempGegnerTyp.Name
      WriteLine Datei, TempGegnerTyp.HPMax
      WriteLine Datei, TempGegnerTyp.GiveExp
      WriteLine Datei, TempGegnerTyp.Schaden1
      WriteLine Datei, TempGegnerTyp.Schaden2
      WriteLine Datei, TempGegnerTyp.MagischerSchaden1
      WriteLine Datei, TempGegnerTyp.MagischerSchaden2
      WriteLine Datei, TempGegnerTyp.Ruestung
      WriteLine Datei, TempGegnerTyp.Geschwindigkeit
      WriteLine Datei, TempGegnerTyp.AngriffsRadius
      WriteLine Datei, TempGegnerTyp.AttackeID
      WriteLine Datei, TempGegnerTyp.ZauberID
      WriteLine Datei, ""
   Next
   CloseFile Datei
End Function


Gespeichert wird nach jedem Beenden mit Escape.
Das Problem ist nur: Wenn ich bei meinem NPC-Editor (Link mit Bild einen neuen NPC erstelle (man kann auf die Werte klicken und diese dann durch Eingabe verändern) und diesen mit "OK" zur Liste hinzufüge, und danach Escape drücke, bekomme ich eine Fehlermeldung "Unhandled Exception: Attempt to access field or method of Null object", wobei diese Zeile markiert wird:
Code: [AUSKLAPPEN]
WriteLine Datei, TempNPC.ID

Nach der Debug Spalte der rechten Seitenleiste bei "Function Speichern" ist "Local Datei:TStream=Null" und "Local TempNPC:TCharakter=$01c44930" und dieser hat dieselben Field-Einträge, die ich ihm vorher zugewiesen habe (man kann ja auf das + klicken und sich dann die Werte ansehen).
Bei "Function WriteLine" ist "Local stream:TStream=Null" und " Local str:String="1" ". Und bei "Function NPC-Editor" (womit die gesamte Datei gemeint ist) ist "Global NPC:TCharakter=$01c44930" und "Global NPCList:TList=$00ec1c60".

Die Datei "NPCs.txt" existiert aber und müsste ja durch WriteFile() sowieso erstellt werden, wenn sie nicht vorhanden sein sollte.

Mysteriös daran ist aber: Wenn ich einen NPC erstelle, bei dem ich den Feldern Geschwindigkeit, x1, x2, y1 und y2 keine Werte durch den Editor zuweise, funktioniert es. Wenn ich aber z.B nur ID und Geschwindigkeit festlege, geht es auch. px und py kann man beim Editor durch klicken auf die Map bestimmen, das muss man nicht manuell eingeben. SFrame ist von alleine 7 und MapName ist der derzeitige MapName (also welche Karte zurzeit auf dem Bildschirm zu sehen ist). Alles andere müsste man manuell durch den NPC-Editor eingeben.
Bei den Gegnern meckert er aber nie rum, und bei den Gegner-Typen auch nicht, obwohl Gegner und NPCs sich ja (so gesehen) recht ähnlich sind.

Heute habe ich dann noch den Item-Editor gemacht, mit welchem man Items, Zauber und Behälter erstellen und (Behälter) auf die Karte setzen kann. Der funktioniert genauso. Hab mich am Anfang schon gefreut, dass bei dem das Speichern mal ging, aber dann musste ich feststellen, dass es hier auch nicht 100%ig funktioniert. Wenn ich ein Item erstelle und immer nur ungefähr 3-4 Felder ausfülle, dann geht es. Wenn ich das Programm dann nochmal starte und an diesem Item weiterarbeite, und auch nur wieder 3-4 Felder ausfülle und wieder speicher, geht es auch wieder.
Die Behälter machen bei mir übrigens keine Probleme, haben aber auch nur 3 Felder, die man ausfüllen muss bzw. zwei von drei werden durch einen Klick auf die Karte selbst bestimmt.

Hier ist noch einmal die Speicher-Funktion des Item-Editors:

Code: [AUSKLAPPEN]

Function Speichern()
   Local Datei:TStream
   Datei = WriteFile("Items.txt")
   For Local TempItem:TItem = EachIn ItemList
      WriteLine Datei, TempItem.ID
      WriteLine Datei, TempItem.Name
      WriteLine Datei, TempItem.Art
      WriteLine Datei, TempItem.Typ
      WriteLine Datei, TempItem.Schaden1
      WriteLine Datei, TempItem.Schaden2
      WriteLine Datei, TempItem.Ruestung
      WriteLine Datei, TempItem.Zweihaendig
      WriteLine Datei, TempItem.Wert
      WriteLine Datei, ""
   Next
   Datei = WriteFile("Zauber.txt")
   For Zauber:TZauber = EachIn ZauberList
      WriteLine Datei, Zauber.ID
      WriteLine Datei, Zauber.Name
      WriteLine Datei, Zauber.Art
      WriteLine Datei, Zauber.Typ
      WriteLine Datei, Zauber.Wirkung
      WriteLine Datei, Zauber.BenoetigteMP
      WriteLine Datei, Zauber.LadungMax
      WriteLine Datei, Zauber.Pause1
      WriteLine Datei, Zauber.Pause2
      WriteLine Datei, Zauber.Wert
      WriteLine Datei, ""
   Next
   For Behaelter:TBehaelter = EachIn BehaelterList
      Datei = WriteFile("Behälter/Behälter"+Behaelter.ID+".txt")
      WriteLine Datei, Behaelter.ID
      WriteLine Datei, Behaelter.x
      WriteLine Datei, Behaelter.y
      For Item:TItem = EachIn Behaelter.Inhalt
         WriteLine Datei, Item.ID
         WriteLine Datei, Item.Anzahl
      Next
   Next
   CloseFile Datei
End Function


Genau dasselbe, auch wenn ich keine "Local TempItem:TItem" Variablen benutze.

Hier auch noch die Types, wenn sie euch helfen:

Code: [AUSKLAPPEN]

Type TCharakter
   Field ID:Short
   Field Typ:Byte
   Field Name:String
   Field Gruppe:Byte
   Field Image:TImage
   Field FaceImage:TImage
   Field MapName:String
   Field px:Short
   Field py:Short
   Field Geschwindigkeit:Float
   Field SFrame:Byte = 7
   Field x1:Short
   Field x2:Short
   Field y1:Short
   Field y2:Short
End Type

Type TGegner
   Field ID:Short
   Field Typ:Byte
   Field Image:TImage
   Field Gruppe:Byte
   Field MapName:String
   Field px:Short
   Field py:Short
   Field Geschwindigkeit:Float
   Field x1:Short
   Field x2:Short
   Field y1:Short
   Field y2:Short
End Type

Type TGegnerTyp
   Field ID:Byte
   Field Name:String
   Field HPMax:Short
   Field Schaden1:Byte
   Field Schaden2:Byte
   Field MagischerSchaden1:Byte
   Field MagischerSchaden2:Byte
   Field Ruestung:Byte
   Field Geschwindigkeit:Float
   Field AngriffsRadius:Byte
   Field GiveExp:Short
   Field AttackeID:Byte
   Field ZauberID:Byte
End Type


Code: [AUSKLAPPEN]

Type TItem
   Field ID:Short
   Field Name:String
   Field Art:String
   Field Typ:String
   Field Image:TImage
   Field AnimImage:TImage
   Field Schaden1:Byte
   Field Schaden2:Byte
   Field Ruestung:Byte
   Field Zweihaendig:Byte
   Field Wert:Short
   Field Anzahl:Byte = 1
End Type

Type TZauber
   Field ID:Short
   Field Name:String
   Field Art:String
   Field Typ:Byte
   Field Image:TImage
   Field AnimImage:TImage
   Field Wirkung:Byte
   Field BenoetigteMP:Byte
   Field LadungMax:Short
   Field Pause1:Short
   Field Pause2:Short
   Field Wert:Short
End Type

Type TBehaelter
   Field ID:Short
   Field x:Short
   Field y:Short
   Field Inhalt:TList = New TList
End Type


Ich dachte, dass es vielleicht etwas mit der Größe eines NPCs bzw. Items (in Bytes) zu tun hat. Aber die paar Bytes werden doch kein Problem für WriteFile/WriteLine sein, oder? Oder kann es an irgendeiner Einstellung liegen? Normalerweise hatte ich aber nie Probleme mit WriteFile.


Ich bin für jede Hilfe dankbar! Falls ihr noch mehr Code benötigen solltet, einfach bescheid sagen.

Ich hoffe ihr habt eine Idee, was das für ein Fehler sein könnte, weil mir ist das einfach unerklärlich.
Danke schon mal im Voraus!

MFG Lador
Mein aktuelles Projekt:
2D-Rollenspiel "Iliran"
Screenshot | Worklog
Fortschritt: ca. 70%
 

#Reaper

Newsposter

BeitragMi, Nov 04, 2009 22:57
Antworten mit Zitat
Benutzer-Profile anzeigen
Also ohne lange drüber nach zu denken:
Wie wäre es, wenn du direkt nach WriteFile() die entsprechende Variable einfach auf != Null überprüfst? Das wäre wohl das offensichtlichste, woran es liegen könnte und somit als erstes zu prüfen..
Eventuell fehlen die Schreibrechte für die Datei (Schreibschutz z.B.).
Ansonsten könnte es auch sein, dass das Object hinter TempNPC nicht (mehr) existiert? Vielleicht hast du es evtl. irgendwo deleted, aber es in der Liste gelassen?

Ansonsten würde ich dir noch empfehlen, die TList's deiner Types in das jeweilige Type hinein zu stecken, z.B. unter dem Namen "_List" o.Ä. Aber das nur als Vorschlag von mir. Wink

MfG
#Reaper
AMD Athlon 64 3500+, ATI AX800 Pro/TD, 2048 MB DRR 400 von Infineon, ♥RIP♥ (2005 - Juli 2015 -> sic!)
Blitz3D, BlitzMax, MaxGUI, Monkey X; Win7
 

Lador

BeitragDo, Nov 05, 2009 12:16
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke für die Antwort.

Ich hab einmal "If Datei = Null Then RuntimeError "Datei nicht gefunden" ", allerdings hilft mir das trotzdem nicht bei der Lösung des Problems. Der RuntimeError hat natürlich genauso angeschlagen, wie die Fehlermeldung von BlitzMax auch.

Unter Rechtsklick->Eigenschaften/Attribute sieht man, dass die Datei weder schreibgeschützt noch versteckt ist. Unter Erweitert ist "Datei kann archiviert werden" und "Inhalt für schnelle Dateisuche indizieren" angekreuzt, allerdings auch bei den Dateien, die nicht gleich Null sind.

Wie meinst du das?
Zitat:
Ansonsten könnte es auch sein, dass das Object hinter TempNPC nicht (mehr) existiert? Vielleicht hast du es evtl. irgendwo deleted, aber es in der Liste gelassen?


MFG Lador
Mein aktuelles Projekt:
2D-Rollenspiel "Iliran"
Screenshot | Worklog
Fortschritt: ca. 70%

Alfadur

BeitragDo, Nov 05, 2009 15:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Sicher das die NPCList nicht leer ist? Versuch mal vorher debuglog NPCList.count() ...
A Cray is the only computer that runs an endless loop in less than four hours.
 

#Reaper

Newsposter

BeitragDo, Nov 05, 2009 19:15
Antworten mit Zitat
Benutzer-Profile anzeigen
@Alfadur: Wenn die Liste leer wäre, würde er die Schleife eh nicht durchgehen.

@Lador:
Nun.. ich weiß nun gar nicht mehr genau wie das bei BMax ist, aber man kann ja Objekte(=Instanzen) eines Types löschen.. nunja, da habe ich glaube ich einen Denkfehler gemacht. Löschen direkt kann man in BMax keine Instanzen mehr, die werden ja vom GC gelöscht, sobald alle Variablen dazu auf Null gesetzt wurden, oder so... Korrigiert mich. Wink

Aber der Fehler ist ja ein anderer.
Ich weiß nun nicht genau wie WriteFile arbeitet (die Dokumentation dazu ist ja auch recht dürftig), aber kann man damit eigentlich bereits existierende Dateien wieder öffnen? (Verwechsle ich vllt. gerade mit einer anderen Sprache..)
Ansonsten weiß ich nun auch nicht weiter, als Rechte, Pfade etc. zu prüfen.
AMD Athlon 64 3500+, ATI AX800 Pro/TD, 2048 MB DRR 400 von Infineon, ♥RIP♥ (2005 - Juli 2015 -> sic!)
Blitz3D, BlitzMax, MaxGUI, Monkey X; Win7
 

Schnuff

BeitragDo, Nov 05, 2009 20:09
Antworten mit Zitat
Benutzer-Profile anzeigen
Hast du mal einen neustart probiert?
Manche Programme (eigentlich alle) blockieren den schreibzugriff auf eine Datei, wenn sie diese gerade beschreiben.
Es könnte beispielsweise sein, das die Datei irgentwie geöffnet ist?
Fllt. ist auch noch ein Prozess deines Editors am laufen, der diese Datei blockiert
oder ein proßess hat die Datei nicht mit Closefile wieder freigegeben (wegen eines Absturzes)?

Wie das unter BMax gehandhabt wird weiß ich nicht, allerdings währe es interessant, zu erfahren ob ein Neustart das Problem löst...
Programmers dont die. They gosub without return...
 

Lador

BeitragFr, Nov 06, 2009 12:27
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke nochmals für die vielen Antworten.

Alfadur:
Wie Reaper gesagt hat, würde dann die Schleife nicht durchlaufen werden. Außerdem ist ja Datei=Null, an der Liste liegt es nicht. (Ich habs übrigens trotzdem mal probiert und er hat die entsprechende Anzahl, und nicht 0, angezeigt.)

Reaper:
Zitat:
Function WriteFile:TStream( url:Object )
Open a file for output.

Also nach der Beschreibung kann man mit WriteFile eine Datei öffnen, aber nur zum Schreiben. Es gibt auch noch OpenFile(), da kann man sowohl schreiben als auch lesen. Hab ich aber auch schon probiert. Ich hab die Dateien ja auch zuerst mit WriteFile() erstellt, und nicht manuell mit Notepad.

Schnuff:
Du meinst einen Computer-Neustart? Ich arbeite schon seit ein paar Tagen an den Editoren, und in der Zwischenzeit hab ich meinen Computer schon öfters runtergefahren und wieder hochgefahren.


Ich hab vorhin bemerkt, dass wenn man die Speicher-Reihenfolge der Dateien von NPCs-Gegnern-GegnerTypen zu Gegnern-NPCs-GegnerTypen ändert, stürzt er schon bei den Gegnern ab, falls man einen neuen NPC (?) erstellt hat (was irgendwie noch weniger Sinn ergibt, als dass er beim NPC-Speichern abstürzt, wenn man einen neuen NPC erstellt hat).

Ich hab jetzt einfach mal für euch eine RAR hochgeladen, falls ihr euch das mal selbst anschauen wollt. Vielleicht geht es ja bei euch. ^^ Einfach im Archiv nach "Iliran NPC-Editor" suchen, sollte ja recht weit oben stehen.

MFG Lador
Mein aktuelles Projekt:
2D-Rollenspiel "Iliran"
Screenshot | Worklog
Fortschritt: ca. 70%
 

klepto2

BeitragFr, Nov 06, 2009 13:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe denke ich ein Problem gefunden, auch wenn das Problem mit dem NPC Editor hier nicht nachvollziehbar war. Bis jetzt.

In deiner Item Speicherfunktion vergisst du einfach das CloseFile für jede Datei bis auf die letzte. Dadurch sind die ersten Dateien natürlich beim 2. Aufruf gesperrt. (Bis auf die letzte)

Das kann zu Problemen führen.

Überprüfe mal wo du dein Projekt gespeichert hast (Stichwort UAC Probleme im Programme Ordner)
Matrix Screensaver
Console Modul für BlitzMax
KLPacker Modul für BlitzMax

HomePage : http://www.brsoftware.de.vu
 

Lador

BeitragFr, Nov 06, 2009 13:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja, das Problem ist nur, dass die Dateien auch schon beim ersten Aufruf gesperrt sind.

Ich hab die zwei fehlenden CloseFile(s) hinzugefügt (wie bei der Speicherfunktion des NPC-Editors), und es geht trotzdem nicht.

Der NPC-Editor (erste Speicherfunktion) geht ja auch nicht.

Danke trotzdem für die Antwort!

MFG Lador
Mein aktuelles Projekt:
2D-Rollenspiel "Iliran"
Screenshot | Worklog
Fortschritt: ca. 70%

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group