Registriert: So Jun 01, 2008 16:06 Beiträge: 31 Wohnort: Nürtingen
Öhm, ab nun Deutsch oder Englisch?
Ich nehm mal stark an, Englisch.
Thanks a lot. I tried this and that and I'm sure tfilestream is the fastest and cleanest way to get my mapdata out of my external file.
But all of them read a file and then do something else with it like an array or a stringlist.
In fact the shortest and most perfomance saving way for me would be to load my file in to a filestream and to read out the tile-information of the tiles I see, everytime when my gltranslatef(x,y,z) is moving.
So I can't see any reason to load a filestream and then put all data in an array?
Whan i have right now is:
Code:
var
mapstream : tfilestream;
maplen :longint;//I need this when I want to read out more than 1 byte?
//As I only need 1 byte now I set maplen:=1;
mapdata :integer;//This is the number of the tile-type.
This Seek-thing must fit in. But I'm not sure about these mapstream.Read-lines. Somehow it seems not to be possible to find any example of a simple reading out of a filestream Oo
The Problem with Seek is that it is a function. And when I add this function to public Delphi wants me to add a Form.Seek(blabla-thing (dunno what the name of such a part is). And I don't know what information Delphi wants there Oo
Seek's delaration is done and all parameters Seek needs are there i think.
Registriert: So Jun 01, 2008 16:06 Beiträge: 31 Wohnort: Nürtingen
okay, danke. Je länger ich englisch schreib, desto schlechter find ich meins -.-
LChar ist ein string.
Du gibst ihm einen Inhalt, das 'X'.
Und wenn ich Read(LChar[1],1) mach, will er einen Array-Typ haben.. =/
d.h. ich muss meinen Stream auslesen und doch als 2D-Array speichern. Erst dann kann ich sinnvoll drauf zugreifen?
Angenehm ._.
Dann geh ich mal Array-Tutorials weiter durchstöbern..
Es sind immer Kleinigkeiten, die am Ende nicht wollen. Hier zB. Was ist ein DatenArray? Delphi will das nicht. Ich probier mal einfach Array. Und dann mal sehen, wie weit ich komme..
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Stream.Read und Stream.Write möchte einfach nur eine Variable übergeben haben in der es die Daten ablegen soll.
Code:
Read(Byte,1);
Read(Integer,4);
Bei Strings ist es wichtig, dass man das erste Zeichen übergibt. Denn Strings sind Pointer und wenn man Read(String, 4) übergibt würde er in die Variable hineinschreiben. Bei Read(String[1], 4) würde er aber die Daten bekommen.
Du kannst aber prinzipiell ALLES an Read übergeben. Das muss nur das sein was du lesen willst und du musst auch die passende Größe übergeben.
Registriert: Mo Sep 23, 2002 19:27 Beiträge: 5812
Programmiersprache: C++
Um sich die Sache zu erleichtern gibt es für das direkte Lesen und Schreiben verschiedener Typen auch noch die Helferklassen TWriter und TReader. Damit kann man auch z.B. direkt Strings aus einem Stream lesen/rein schreiben, ohne sich selbst um Größen kümmern zu müssen. Kleines Beispiel :
Registriert: So Jun 01, 2008 16:06 Beiträge: 31 Wohnort: Nürtingen
Aber das würde irgendwas IN den stream schreiben, oder?
Nochmal von vorn:
Der Stream beinhaltet nur Bytes. Sieht er die als String oder kann ich sie direkt als Zahl, die in dem Byte ist nehmen?
Und die 2. Frage, wie schreibe ich 1 bestimmtes Byte (z.B. das 45ste Byte des Streams) in eine gewöhnliche Integer- oder Bytevariable?
Ich suche und google und probier fast schon bilnd alles aus. stream.WriteLn, stream.WriteBuffer, etc etc. variable:=stream.position; war der erfolgreichste Versuch, gibt jedoch aus, an welcher Position im Stream ich mich gerade befinde und nicht das Byte, das an dieser Position ist -.-
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
noeska: TWriter und TReader werden von der VCL benutzt um die Formulare aus den Resource zu laden. Entsprechend sind die schon wirklich sehr lange dabei.
TReader und Strings: Damit wäre ich eventuell Vorsichtig. Denn für Strings braucht man zwingend eine Größenangabe. Sonst weiß der Lesende nicht wie groß der String ist. Auch die Größenangabe braucht eine Größe (byte, word, dword). Wenn man mit TWriter den Stream erstellt hat ist das kein Thema. Nur wenn das ein vorhandenes Format ist was man einlesen möchte wäre ich damit vorsichtig.
ecth: Dem TStream ist es egal was er dort als Daten hat. Du kannst den Stream entweder Byteweise, Integerweise oder aber auch in einen String einlesen. TStream ließt die Daten ein und schreibst sie in die von dir übergebene Variable. Was die für einen Typen hat ist deine Entscheidung und ist dem Stream herzlich egal.
Als Beispiel mal wie du das 45te Byte ausließt.
Code:
var
ByteValue:Byte;
begin
// Position setzen
Stream.Position:=45;
// Byte auslesen
Stream.Read(ByteValue,1);
Wichtig dabei. Wenn du ein Byte auslesen möchtest, dann musst du auch eine ByteVariable an Read übergeben. Wenn du dieses Byte in einen Integerwert lesen würdest, dann würdest du nur das höchste Byte davon setzen. Alle anderen Bytes des Integers wären undefiniert und somit wären deine Werte murks. Außer du würdest das noch irgendwie filtern aber so ein Aufwand wäre absoluter quatsch.
Wenn du einen Integerwert auslesen möchtest, dann musst du auch eine Integervariable übergeben und entsprechend 4 Bytes auslesen lassen.
Registriert: Di Okt 03, 2006 14:07 Beiträge: 1277 Wohnort: Wien
Hier ein Beispiel für Strings aus dem "Developers Guide" von Delphi 5, Seite 3-44:
Code:
procedure cast_string;
var
fs: TFileStream;
s:string='Hello';
begin
fs := TFileStream.Create('Temp.txt', fmCreate or fmOpenWrite);
fs.Write(s,Length(s));// Liefert Datenmüll
fs.Write(PChar(s)^,Length(s));// Das ist die richtige Methode
end;
Aber Achtung! "s" ist ein AnsiString. Das ist wichtig heutzutage, wo alle so wild auf UTF8 sind. Die Kommentare zum Sourcecode stammen übrigens nicht von mir, sondern vom Autor des Entwicklerhandbuchs.
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Das muss aber schon älter sein. Denn heute würde man eher die Variante mit s[1] nehmen (hat allerdings die gleiche wirkung - muss ja, sonst würde es nicht funktionieren. Aber mit [1] gehts ganz sicher auch unter FreePascal, sogar ohne {$mode delphi}) und außerdem mag delphi keine Initialisierungen in Lokalen
Variablen (zumindest mochte mein D6/D7 das nie)... [und da ist nen Speicherleck, aber das ist wohl nebensache].
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Registriert: Di Okt 03, 2006 14:07 Beiträge: 1277 Wohnort: Wien
Ja das ist schon älter, es ist wie gesagt ein Beispiel aus dem "Developers Guide" von Delphi 5. Und ja, da ist ein Speicherleck. Und auch ja, s[1] wäre vielleicht klüger zu schreiben. Und OK, dieses Initialisieren ist mir auch fremd. Also korrigieren wir das offizielle Handbuch auf eine etwas aktuellere Version:
Code:
procedure WriteStringToFileStream;
var
fs: TFileStream;
s:AnsiString;
begin
fs:= TFileStream.Create('Temp.txt', fmCreate or fmOpenWrite);
Registriert: So Jun 01, 2008 16:06 Beiträge: 31 Wohnort: Nürtingen
Okay, vielen, vielen Dank Oo
Ich hab das Ding aus dem Handbuch gelesen, aber mich irritierte immer dieses (s, length(s)), weil viele Tutorials ne Variable für die Länge besetzt haben und ich einfach nicht verstand, wozu zum Geier die ne Länge brauchen.
(s[1], length(s)) kommt bei mir gern ein Fehler, weil Delphi2005 da immer einen Arra-Typ verlangt. Dieses "variable[eckklammer zur bestimmung], komma anderer wert" muss Delphi wohl sehr an Array erinnern... ôo
lenght(s) ist vorsichtiger, weil er die Länge meiner Variable nimmt und somit Fehler umgangen werden.
Ist es aber nicht Zeitaufwändiger einen Wert erst im Hintergrund erkennen zu lassen anstatt ihn anzugeben?
Klar, Sekundensparerei.. Aber nur so o,o
Na ja, auf jeden Fall danke. Ich glaube jetzt besser zu verstehen, wie das aufgebaut ist. Sobald ich am Laptop bin (wo mein Delphizeugs auch ist) wirds ausprobiert ^^
[ edit: ]
Okay, was bisher echt funktioniert hat war:
Wenn ich die Variable nun Integer mach, dann krieg ich vielzuviele Zahlen (4 halt) und wenn ich ein Byte mach, krieg ich Hexadezimalzahlen, oder? xD
Vorallem das, was in der Textdatei ne 0 ist, ist im Stream der Hex-Wert des Asci-Zeichens '0'..
Aber nochmals Danke. Was nicht ging, geht. Der Rest ist nur noch Tüftelei ^^
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Hexadezimal ist nur ein anderes Zahlensytem. Die Zahl darunter ist aber immer noch die Gleiche. Hexadezimal besteht aus Nibbles. Ein Nibble kann 16 Wert annehmen. 0-9, und A-F. Zwei Nibbles ergeben 1 Byte. Wärend das größere Nibble den oberen 4 Bits entspricht und das untere Nibble den unteren 4 Bits.
Der Ascii Wert des Zeichens '0' hat im übrigen wiederrum einen ganz anderen Wert. Wenn du also im Editor '0' eintippst, dann hat das Byte den Wert $30 (Hex) oder 48 (Dec).
Beziehen sich deine Fragen jetzt eigentlich immer noch auf das leicht einzulesende Dateiformat? Die Ansicht wie die Datei aufgebaut ist ähnelt zwar dem eines Hexeditors nur sind die Daten anders abgelegt. Du musst in deinem Falle die beiden Bytes seperat einlesen, den enthaltenen Text in einen Dezimalwert umrechnen und dann die beiden Nibbles zu einem ganzem zusammen setzen.
Vielleicht würde die Benutzung einer TStringList schon etwas bringen. Denn TStream ist zum einlesen von binärdateien gedacht. Für Texte muss man da schon etwas aufpassen. Mit TStringList kannst du komplette Dateien einlesen und dann Zeilenweise darauf zugreifen. Du müsstest dann nur den String in der Datei in einen Integer verwandeln.
Oder aber eventuell wäre es einfacher, wenn du dir ein leichteres System ausdenkst? Je nachdem für was es ist und wie viel arbeit du dort hineinstecken möchtest. Ein Editor der dann Mapdateien in einem Format ablegen kann was deutlich einfacher einzulesen ist als das aktuelle. Dann läuft halt alles über deinen Editor und nicht über x beliebige TextEditoren.
PS: Zum Umwandeln eines HexStrings in einen Integerwert kannst du auch StrToInt benutzen. Du musst nur vor dem Aufruf '$' an den Anfang des Textes setzen. Das ist allerdings alles andere optimal und normal würde ich so etwas auch wirklich nicht empfehlen.
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
SizeOf klappt zwar, aber nur für "finale" Variablen. Das sind zum Beispiel Records (die keine nicht-finalen Variablen enthalten), Statische Arrays (ohne einen nicht-finalen Typ), Integer, Single, Double, aber nicht String. String ist ein Typ, der dynamisch behandelt wird. Eigentlich ist "String" nur ein Pointer. Und zwar auf das erste Zeichen im String wenn ich mich recht entsinne. Und VOR dem ersten Zeichen liegen dann im Speicher noch die Länge und die anzahl der Referenzen auf den String (wenn letztere = 0 ist, wird der Speicher freigegeben).
Deshalb musst du für Strings Length anstatt SizeOf nehmen. SizeOf dürfte entweder garnicht funktionieren oder 4 zurückgeben oder eventuell vom Compiler automatisch in Length umgewandelt werden (was ich aber bezweifle).
Wie Lossy schon gesagt hat, wenn du wirklich eine Textdatei zeilenweise einlesen willst, solltest du eher TStringList nehmen. Das ist dafür definitv besser geeignet.
Und ich bitte dich um etwas: Könntest du bitte deinen ersten Post auf dieser Seite "Öhm, ab nun Deutsch oder Englisch? Ich nehm mal stark an, Englisch. ... " editieren und im Quelltext die Kommentare abkürzen/über mehrere Zeilen verteilen? Die Scrollbar die durch deine langen Zeilen entsteht ist sehr unangenehm und macht das Lesen echt schwierig.
Gruß Lord Horazont
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Mitglieder in diesem Forum: 0 Mitglieder und 11 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.