AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Problem mit TFileStream.Read

Ein Thema von Lumpiluk · begonnen am 5. Apr 2010 · letzter Beitrag vom 6. Apr 2010
Antwort Antwort
Benutzerbild von Lumpiluk
Lumpiluk

Registriert seit: 25. Dez 2008
110 Beiträge
 
#1

Problem mit TFileStream.Read

  Alt 5. Apr 2010, 11:42
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:
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
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:
Delphi-Quellcode:
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 Editor funktioniert das Laden perfekt, allerdings kommt im eigentlichen Spiel beim Laden derselben Datei bei der If-Abfrage diese Exception:
"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 )
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#2

Re: Problem mit TFileStream.Read

  Alt 5. Apr 2010, 11:48
es ist reines glück das im Editor kein Fehler kommt. Anstelle von
MazeStream.Read(TmpStr, StrLength); muss es
MazeStream.Read(TmpStr[1], StrLength); 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.
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);
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Benutzerbild von Lumpiluk
Lumpiluk

Registriert seit: 25. Dez 2008
110 Beiträge
 
#3

Re: Problem mit TFileStream.Read

  Alt 5. Apr 2010, 14:07
Danke, jetzt klappt's!

Zitat von SirThornberry:
Delphi-Quellcode:
SetLength(TmpStr, StrLength);
MazeStream.Read(TmpStr[1], StrLength);
So kam allerdings nur die Hälfte des Strings an, aber dank dieser seite habe ich es jetzt so hinbekommen (vielleicht hilft es noch irgendwem...):
Delphi-Quellcode:
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.5then
      begin
        //...
      end;
    finally
      MazeStream.Free;
    end;
  end;
end;
Vielen Dank nochmal!
  Mit Zitat antworten Zitat
Benutzerbild von wicht
wicht

Registriert seit: 15. Jan 2006
Ort: Das schöne Enger nahe Bielefeld
809 Beiträge
 
Delphi XE Professional
 
#4

Re: Problem mit TFileStream.Read

  Alt 5. Apr 2010, 14:17
MazeStream.Write(ValidationString[1], StrLength*SizeOf(ValidationString[1])); Ich finde folgendes schöner:

MazeStream.Write(String[1], StrLength * SizeOf(Char)); 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.
http://streamwriter.org

"I make hits. Not the public. I tell the DJ’s what to play. Understand?"
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#5

Re: Problem mit TFileStream.Read

  Alt 5. Apr 2010, 14:53
Ü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.
  Mit Zitat antworten Zitat
Benutzerbild von Lumpiluk
Lumpiluk

Registriert seit: 25. Dez 2008
110 Beiträge
 
#6

Re: Problem mit TFileStream.Read

  Alt 6. Apr 2010, 11:02
Zitat:
statt .Read() und .Write() sollte man als Benutzer eines Stream immer .ReadBuffer() und .WriteBuffer() verwenden.
OK, habe ich gemacht.
Was ist denn da genau der Vorteil? Und wofür sind dann das normale Read und Write da?
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
37.228 Beiträge
 
Delphi 10.4 Sydney
 
#7

Re: Problem mit TFileStream.Read

  Alt 6. Apr 2010, 11:06
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.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
Delphi-Tage 2005-2014
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#8

Re: Problem mit TFileStream.Read

  Alt 6. Apr 2010, 11:11
Dann verwende ich doch lieber weiterhin Read und Write und werte das Ergebnis aus anstelle Exceptions anfangen zu müssen.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
37.228 Beiträge
 
Delphi 10.4 Sydney
 
#9

Re: Problem mit TFileStream.Read

  Alt 6. Apr 2010, 11:17
Zitat von SirThornberry:
Dann verwende ich doch lieber weiterhin Read und Write und werte das Ergebnis aus anstelle Exceptions anfangen zu müssen.
Das ist auch OK so ... jedenfalls wenn du das Ergebnis auch auswertest, was leider viele immer mal wieder vergessen.

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.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
Delphi-Tage 2005-2014
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:17 Uhr.
Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf