Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Fr Jul 18, 2025 11:52

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 16 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Autor Nachricht
BeitragVerfasst: Do Feb 19, 2004 16:59 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Ich wollte grade meine Packageunit so erweitern, das ich die Packages (in denen z.B. meine Texturen und Modelle drin sind) auch direkt als Resource an die Exe hängen kann. Das Anhängen klappt recht gut, aber beim Laden gibts komischerweise ein Problem das mich seit Stunden nervt, nämlich die Tatsache das mein TReader mir direkt am Anfang nen Lesefehler ausgibt.

Wenn ich mein Package von der Platte in den Stream lade, gehts ohne Probleme :
Code:
  1. var
  2.  Reader : TReader;
  3.  i      : Integer;
  4. begin
  5. ...
  6. Stream := TMemoryStream.Create;
  7. Stream.LoadFromFile(pFileName);
  8. Reader := TReader.Create(Stream, 128);
  9. i := Reader.ReadInteger;

Klappt einwandfrei, und in i steht genau das drin was rein soll.

Lade ich nun das Package aus der der EXE angehängten Resource, gibt mit der TReader direkt nen EReadError :
Code:
  1. var
  2.  Reader    : TReader;
  3.  i         : Integer;
  4.  ResStream : TResourceStream;
  5. begin
  6. ...
  7. Stream    := TMemoryStream.Create;
  8. ResStream := TResourceStream.Create(hInstance, pResName, 'TPACKAGE');
  9. Stream.CopyFrom(ResStream, ResStream.Size);
  10. Reader := TReader.Create(Stream, 128);
  11. i := Reader.ReadInteger;


Ich versuche jetzt seit bestimmt knapp 2h rauszufinden wo denn bei zweitem Ladekomplex das eigentliche Problem liegt. Ich hab testweise sogar mal den ResStream und den Stream bei Methode 2 auf Platte zwischengespeichert und in mein Packagetool geladen, und beide Dateien haben einwandfrei funktioniert bzw. hatten den selben Inhalt wie das Package auf der Platte.

Evtl. hat ja einer von euch schonmal mit Streams und dem TReader gearbeitet und kann mir weiterhelfen. Die Kombo TReader/TWriter+T(irgendwas)Stream hat mir nämlich schon so manche Probleme gemacht, die ich bisher aber alle selbst lösen konnte.

Kleiner Nachtrag : Wenn ich direkt die Methode Read des Streamobjektes nutze, dann klappts. Allerdings ist das TReader-Objekt weitaus bequemer und macht auch das Laden dynamischer Strings aus einem Stream sehr einfach.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Feb 19, 2004 19:28 
Offline
DGL Member

Registriert: Mo Jan 20, 2003 20:10
Beiträge: 424
Wohnort: nähe Starnberg
Hast Du mal ein Testprojekt zur Hand, mit dem ich den Fehler nachvollziehen kann?

Gruß
KidPaddle

_________________
http://www.seban.de


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Feb 19, 2004 19:30 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Es könnte sein, das die Position des Streams nach dem Aufruf von CopyFrom am Ende steht. Die VCL Komponenten lesen auch aus der Ressource. Vermutlich wird da direkt aus dem RessourcenStream gelesen und keine Kopie erstellt.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Feb 19, 2004 19:43 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
@KidPaddle :
Leider nicht, ist Teil eines größeren Projektes und da ich nicht will das jeder meine Packages lesen kann hab ich auch nix was ich rausgeben kann. Ich werd aber evtl. die Tage was zusammenbauen.

@Lars :
Das hab ich zuerst auch gedacht, aber selbst wenn ich die Anfangsposition beider Streams zurücksetze kommt der selbe Fehler. Auch wenn ich nicht aus dem Memorystream, sondern aus dem Resourcenstream lese.
Das Problem tritt wie gesagt nicht auf wenn ich die Read-Methode des Streams benutze. Allerdings ist die TReader-Klasse halt sehr bequem und lässt über die passenden Funktionen (z.B. ReadString, ReadInter, usw.) ein leichtes auslesen diverser Datentypen aus dem Stream zu. Werd ich wohl im Endeffekt doch den TReader (der mich schon einige Nerven gekostet hat) über Bord werfen müssen :(
Das eigenartige ist ja wie gesagt die Tatsache (hab den Res-Stream auf Platte gespeichert), das der Inhalt genau der selbe ist wie wenn ich aus nem Filestream lese und diesen dann in nen TMemoryStream kopiere. Aber in der Hilfe wird leider nirgendwo erwähnt ob/wie sich ein TResourceStream von nem TMemoryStream unterscheidet bzw. was man im Zusammenhang mit der TReader-Klasse beachten muss.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Feb 19, 2004 20:08 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Es könnte sein, daß man erst mit Stream.ReadResHeader den Ressourcen Header überspringen muß.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Feb 19, 2004 20:20 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Nein, daran liegts nicht. Wie ich gesagt habe, geht folgendes ohne Probleme :
Code:
  1. Stream    := TMemoryStream.Create;
  2. ResStream := TResourceStream.Create(hInstance, pResName, 'TPACKAGE');
  3. Stream.CopyFrom(ResStream, ResStream.Size);
  4. Stream.Read(i, SizeOf(i));
  5.  

wohingegen folgendes :
Code:
  1. Stream    := TMemoryStream.Create;
  2. ResStream := TResourceStream.Create(hInstance, pResName, 'TPACKAGE');
  3. Stream.CopyFrom(ResStream, ResStream.Size);
  4. Reader := TReader.Create(Stream, 128);
  5. i := Reader.ReadInteger;
  6.  

den besagten Readerror bringt.

Ich vermute hier irgendwie nen Fehler der durch Zufälle in dieser Konstellation auftritt, da der Reader ja an anderer Stelle einwandfrei funzt. Werde das dann wohl ohne Reader machen müssen.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Feb 19, 2004 20:37 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Vor jedem Wert steht auf dem Stream noch das Format, des Wertes. ReadInteger liest daher nicht nur einen Integer ein. Wenn man des Stream mit dem TWriter erstellt hat, sollte das aber eigentlich kein Problem sein.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Feb 19, 2004 20:40 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Ja, wie gesagt besteht das Problem nur dann, wenn ich die Daten des Streams aus einem TResourceStream übernehme. In der LoadFromFile-Funktion lade ich den MemoryStream direkt von der Platte, nutze aber auch dort TReader, weil mein Packageeditor mit TWriter arbeitet. Dort geht es aber komischerweise einwandfrei, und wenn ich die beiden Streams auf Platte speichere und vergleiche, sind es genau dieselben Dateien.
Ich vermute daher irgendein Problem in der Konstellation TMemoryStream, TResourceStream + TReader. So schlimm ists natürlich nicht, dann lad ich halt die Daten so aus dem Paket, das Anhängen des Pakets an die EXE ist nicht notwendig, sieht aber im Endeffekt eleganter aus.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Feb 20, 2004 08:54 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Eines verstehe ich da nicht ganz. Wieso kopierst du den ResourceStream in einen MemoryStream? Brauchst du den Stream denn öfters zur Laufzeit? Wenn nicht musst es ja nicht unbedingt erst in den Speicher kopieren. Ist ja nur Overhead und Speicher wird der speicher wird zwischenzeitlich auch doppelt belastet.

Aber zu deinem Problem. Ich habe auch keine Ahnung warum sich das zickig anstellt. Aber ich kann dir vielleicht einen anderen Vorschlage machen. Ich hatte auch schon mal recht komplexe StreamOperationen durchführen dürfen. (meine kleine Datenbank und in Firma). Ich habe mir bisher jedes mal einen Satz Methoden geschrieben (Read und Write). So in etwa wie die von dem Reader aber ohne den gesammten Overhead drum herum. Da du ja genau weißt was wann kommt (kommen muss) brauchst du ja auch keine Typüberprüfung etc.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Feb 20, 2004 11:28 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Der TRessourceStream ist ein TCustomMemoryStream, bei dem der Zeiger auf die Addresse der geladene Ressource gesetzt wurde.
Wenn du ein einheitliches Format für die Daten willst, dann würde ich auf die TReader/TWriter verzichten, weil die auf die Komponenten ausgelegt sind und stattdessen eine eigene Version dieser Klassen schreiben. Dann kannst du ja selber immer noch alle Properties durchlaufen und in einem eigenen Format abspeichern. Soweit ich weiß speichert der TWriter nur Komponenten direkt und dann müßte man die ganzen Objekte die man speichern und laden möchte von TComponent ableiten.


Zuletzt geändert von LarsMiddendorf am Fr Feb 20, 2004 11:30, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Feb 20, 2004 11:29 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Lossy eX hat geschrieben:
Eines verstehe ich da nicht ganz. Wieso kopierst du den ResourceStream in einen MemoryStream? Brauchst du den Stream denn öfters zur Laufzeit? Wenn nicht musst es ja nicht unbedingt erst in den Speicher kopieren. Ist ja nur Overhead und Speicher wird der speicher wird zwischenzeitlich auch doppelt belastet.

Ich kopiere den Resourcenstream in einen Memorystream, weil alle Lesefunktionen meiner TPackage-Klasse aus diesem der Klasse zugehörigen TMemoryStream lesen, und ich so nicht immer zwei Funktionen brauche (für TMemoryStream und TResourceStream). Aber natürlich entferne ich den Resourcenstream nachdem ich dessen Inhalt in den MemoryStream kopiert habe wieder aus dem Speicher.

Lossy eX hat geschrieben:
Aber zu deinem Problem. Ich habe auch keine Ahnung warum sich das zickig anstellt. Aber ich kann dir vielleicht einen anderen Vorschlage machen. Ich hatte auch schon mal recht komplexe StreamOperationen durchführen dürfen. (meine kleine Datenbank und in Firma). Ich habe mir bisher jedes mal einen Satz Methoden geschrieben (Read und Write). So in etwa wie die von dem Reader aber ohne den gesammten Overhead drum herum. Da du ja genau weißt was wann kommt (kommen muss) brauchst du ja auch keine Typüberprüfung etc.

Ja, da werde ich wohl nicht rumkommen, wenn ich mein Package unbedingt an die exe anhängen will. Aber evtl. lass ich das auch ganz einfach sein, weil so etwaige Datenupdates vereinfacht werden und ich dann nicht immer die ganze exe mitliefern muss...mal sehen.

Edit @ Lars : Nein, ich hab mir die TWriter/TReader-Klassen mal angesehen, und wenn man nur solche Sachen wie z.B. Write/Read[DatenTyp] nutzt, dann machen die beiden Komponenten im Endeffekt nix anderes als zuerst Infos zum Datentype (z.B. Stringlänge) in den Stream zu schreiben und dann den Inhalt des Datentyps. Allerdings steht in der Hilfe zu TReader/TWriter auch drin das man diese nicht selbst im Programm nutzen soll...werd da wohl wie gesagt was eigenes stricken.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Zuletzt geändert von Sascha Willems am Fr Feb 20, 2004 11:32, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Feb 20, 2004 11:31 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Laß die Klasse doch aus TStream lesen, dann kann sie aus allen Streams lesen. Oder werden bestimmte Elemente von TMemoryStream gebraucht?
Eine andere Idee wäre die Daten einfach direkt an die EXE Datei anzuhängen und dann aus der Datei zu lesen.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Feb 20, 2004 11:36 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Son of Satan hat geschrieben:
Ich kopiere den Resourcenstream in einen Memorystream, weil alle Lesefunktionen meiner TPackage-Klasse aus diesem der Klasse zugehörigen TMemoryStream lesen, und ich so nicht immer zwei Funktionen brauche (für TMemoryStream und TResourceStream).

Streams sind doch so ausgelegt, dass man die über die Basisklasse TStream lesen und schreiben kann. Du müsstest also lediglich beim Erstellen des Streams wissen um was es sich handel und sonst ist es egal was das für ein Stream ist. Die normale OOP Vererbung halt.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Feb 20, 2004 11:48 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Stimmt, k.A. warum ich nicht direkt statt nem TMemoryStream nen normalen Stream genomme habe und den dann über einen temporären TResourceStream bzw. TFileStream lade. Werd das dann heute mal ausprobieren und bescheid geben.
Auf jeden Fall schonmal danke für die Tipps und Anregungen.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Feb 20, 2004 11:55 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Der Ansatz mit dem puren TStream funktionier leider überhauptnicht, denn dann wird ein TStream mit den abstrakten Methoden Read un Write angelegt, und das führt dann egal bei welchem Laden (Datei oder Resource) zu einem abstrakten Fehler.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 16 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.010s | 15 Queries | GZIP : On ]