![]() |
Problem mit TFileStream.Read
Frohe Ostern!
Tut mir Leid, falls der Titel nicht allzu aussagekräftig sein sollte, aber was besseres fällt mir dazu nicht ein:
Delphi-Quellcode:
So sieht der Anfang der Prozedur im einen Projekt aus (ein Editor für ein kleines Spiel, womit ich gerade anfange), und so im eigentlichen Spiel:
procedure TMazeEditor.LoadBinClick(Sender: TObject);
var MazeStream: TStream; x,y, StrLength, dummyInt: Integer; TmpStr: String; TmpByte: Byte; begin if OpenDialog1.Execute then begin try MazeStream := TFileStream.Create(OpenDialog1.FileName, fmOpenRead); MazeStream.Read(StrLength, SizeOf(StrLength)); MazeStream.Read(TmpStr, StrLength); if TmpStr = 'irgendein bestimmter String...' then begin
Delphi-Quellcode:
Im Editor funktioniert das Laden perfekt, allerdings kommt im eigentlichen Spiel beim Laden derselben Datei bei der If-Abfrage diese Exception:
procedure TMazeGame.LoadMazeFromFile(AFile: String);
var MazeStream: TStream; x,y, StrLength, dummyInt: Integer; TmpStr: String; TmpByte: Byte; begin try MazeStream := TFileStream.Create(AFile, fmOpenRead); //der Pfad scheint richtig zu sein MazeStream.Read(StrLength, SizeOf(StrLength)); //StrLength ist hiernach merkwürdigerweise nur 4 MazeStream.Read(TmpStr, StrLength); if TmpStr = 'irgendein bestimmter String...' then //hier kommt der Fehler begin "Im Projekt LS_Maze.exe ist eine Exception der Klasse EAccessViolation mit der Meldung 'Zugriffsverletzung bei Adresse 00405D49 in Modul 'LS_Maze.exe'. Lesen von Adresse FFFFFFFC' aufgetreten." Seltsam finde ich auch, dass nachher trotz "try" eine Fehlermeldung kommt. Das Programm nochmal extra mit Administratorrechten zu starten hat auch nichts gebracht. Woran könnte das liegen? (Ich schätze, ich habe wieder irgendwas Einfaches übersehen ;) ) |
Re: Problem mit TFileStream.Read
es ist reines glück das im Editor kein Fehler kommt. Anstelle von
Delphi-Quellcode:
muss es
MazeStream.Read(TmpStr, StrLength);
Delphi-Quellcode:
heißen. Denn ein String, ein dynamisches Array etc. sind etwas mehr als nur Speicherplatz. Dahinter verbirgt sich eigentlich ein Pointer auf die eigenltichen Daten mit Referenzzählung, Längenangabe etc.
MazeStream.Read(TmpStr[1], StrLength);
Mit TmpStr[1] gibst du sozusagen das erste Zeichen des Strings an und somit wird ab diesem Byte der String beschrieben und nicht die Stelle wo der Pointer etc. sonst ist. Im übrigen musst du vorher natürlich auch die Größe des Strings setzen!
Delphi-Quellcode:
SetLength(TmpStr, StrLength);
MazeStream.Read(TmpStr[1], StrLength); |
Re: Problem mit TFileStream.Read
Danke, jetzt klappt's! :)
Zitat:
![]()
Delphi-Quellcode:
Vielen Dank nochmal!
procedure TMazeEditor.SaveBinClick(Sender: TObject);
var MazeStream: TStream; StrLength: Integer; ValidationString: String; begin if SaveDialog1.Execute then begin try MazeStream := TFileStream.Create(SaveDialog1.FileName,fmCreate); ValidationString := 'der String'; StrLength := Length(ValidationString); MazeStream.Write(StrLength, SizeOf(StrLength)); MazeStream.Write(ValidationString[1], StrLength*SizeOf(ValidationString[1])); //... finally MazeStream.Free end; end; end; procedure TMazeEditor.LoadBinClick(Sender: TObject); //im Spiel ist es fast genau so var MazeStream: TStream; StrLength: Integer; TmpStr: String; begin if OpenDialog1.Execute then begin try MazeStream := TFileStream.Create(OpenDialog1.FileName, fmOpenRead); MazeStream.Read(StrLength, SizeOf(StrLength)); SetLength(TmpStr,StrLength); MazeStream.Read(TmpStr[1], StrLength*SizeOf(TmpStr[1])); if TmpStr = 'www.lumpiluk.de.ms - Maze v0.5' then begin //... end; finally MazeStream.Free; end; end; end; |
Re: Problem mit TFileStream.Read
Delphi-Quellcode:
Ich finde folgendes schöner:
MazeStream.Write(ValidationString[1], StrLength*SizeOf(ValidationString[1]));
Delphi-Quellcode:
Genau so geht es auch beim lesen. Edit: Das liegt übrigens daran, dass Strings in den neuen Delphi Versionen Unicode-Strings sind, und da ein Zeichen eben 2 Bytes belegt.
MazeStream.Write(String[1], StrLength * SizeOf(Char));
|
Re: Problem mit TFileStream.Read
Übrigens:
statt .Read() und .Write() sollte man als Benutzer eines Stream immer .ReadBuffer() und .WriteBuffer() verwenden. Die Argumente sind gleich. Allerdings erzeugen die XXXXBuffer() Methoden eine Exception, falls das Lesen oder Schreiben der Daten nicht vollständig sein sollte. |
Re: Problem mit TFileStream.Read
Zitat:
Was ist denn da genau der Vorteil? Und wofür sind dann das normale Read und Write da? |
Re: Problem mit TFileStream.Read
Das "normale" Read/Write ließt maximal soviele Byte, wie man angibt, aber der genaue Wert wird im Result zurückgegeben, welches man dann auch auswerten sollte.
ReadBuffer/WriteBuffer versuchen genau soviele Bytes zu lesen, wie man angibt und sie haben kein Result. Wenn das nicht ging (z.B. Fehler oder einfach nur das Ende der Datei erreicht/überschritten), dann wird eine Exception ausgelöst. |
Re: Problem mit TFileStream.Read
Dann verwende ich doch lieber weiterhin Read und Write und werte das Ergebnis aus anstelle Exceptions anfangen zu müssen.
|
Re: Problem mit TFileStream.Read
Zitat:
Wenn ich den Fehler behandle und das Auslesen dennoch fortsetzen will, dann verwende ich auch .Read (oder ähnliche Alternativen, da ich immernoch oftmals direkt über die WinAPI geh), aber wenn der Fehler einfach unbehandelt bleiben soll, bzw. geziehlt zu einem Abbruch führen soll, dann verwende ich quasi das ReadBlock ... wozu selber eine Exception auslösen, wenn es sowas schon gibt. :angel2: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:55 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz