PDA

View Full Version : array (understanding?) problem



FlyingFish
11-07-2004, 05:25 PM
Hi all

I've got a (for me) very strange problem. I want to read data from a file via TFileStream into an array.
After the first loop, GMapTempBuffer[0, 0] contains a string like 'test1'. Everything ok so far.
After the next loop I would expect [0, 0] to contain still 'test1' and [1, 0] maybe 'test2'. But no, [0, 0] has been overwritten with 'test2'. [1, 0] is still empty.
Maybe I'm only have a big thinking-problem here, but I don't understand this. Can anybody help? Hope the explanation is not too stupid. :?

Here's the code for that stuff:


var
GMapTempBuffer: array[0..31, 0..31] of string;
c: string;
(...)

FileStream := TFileStream.Create(FileName, fmOpenRead);
try
for y := 0 to 31 do
begin
for x := 0 to 31 do
begin
FileStream.ReadBuffer(PChar(c)^, len);
GMapTempBuffer[x, y] := c;
GroundMap[x, y].Picfilename := GMapTempBuffer[x, y];
end;
end;
except begin
result := false;
FileStream.Free;
exit;
end;
end;

Thanx for any help,

Sven

Useless Hacker
12-07-2004, 01:00 PM
What format is the file you are reading in? You don't seem to be reading the length of the string ("len") anywhere or setting the size of the string with SetLength().

As a reference, here are a pair of generic procedures I use to write and read strings to and from streams. The Length of the string is written to the stream first, then the string data; to read the length is then read back and SetLength called to set the size of the string before reading the data back.
procedure WriteStringToStream(Stream: TStream; const S: String);
var
StrLen: Integer;
begin
{ Get length of string }
StrLen := Length(S);
{ Write length of string to stream }
Stream.WriteBuffer(StrLen, SizeOf(StrLen));
{ Write string to stream }
Stream.WriteBuffer(S[1], (StrLen * SizeOf(Char)));
end;

procedure ReadStringFromStream(Stream: TStream; out S: String);
var
StrLen: Integer;
begin
{ Read length of string from stream }
Stream.ReadBuffer(StrLen, SizeOf(StrLen));
{ Set length of string }
SetLength(S, StrLen);
{ Read string from stream }
Stream.ReadBuffer(S[1], (StrLen * SizeOf(Char)));
end;

FlyingFish
13-07-2004, 10:34 AM
Well, the file i am working with is a map-file for my game, so in the game I won't write to it, only read. Maybe in a map-editor if one will exist someday..

But the length doesn't matter, every string I read has a length of 5 characters. I'm doing the setlength thing in my code, but I forgot to post it.
I changed the ReadBuffer line now and with your code it seems to work.
thanx for that.

sven

FlyingFish
14-07-2004, 11:30 AM
hm, I was wrong, it doens't really work. Well it's reading, but only the first 5 charakters of the file.
With the count parameter in ReadBuffer I only can choose how many bytes should be read from the file, not where the procedure starts to read, can't i?
How can I make it read always the following 5 charakters, not the first ones?

FlyingFish

Useless Hacker
14-07-2004, 02:56 PM
ReadBuffer will always start from the next byte after the previous one read, so it should work. It might help if you posted some more of your code.

FlyingFish
14-07-2004, 05:41 PM
ok, here's the function where I use all the stream stuff.
TMapTile is an object, only the picfilename property is important for here. picfilename is of course a string.



var
GroundMap: array[0..31, 0..31] of TMapTile;

(...)

function LoadGroundMapFromFile(FileName: string): Boolean;
var
FileStream: TFileStream;
c: string;
len: longint;
x, y: Word;
begin
result := true;
len := 5;
x := 5;
y := 0;
setlength(c, len);
FileStream := TFileStream.Create(FileName, fmOpenRead);
try
for y := 0 to 31 do
begin
for x := 0 to 31 do
begin
FileStream.ReadBuffer(c[1], (len * SizeOf(Char)));
GroundMap[x, y].Picfilename := c;
end;
end;
except begin
result := false;
FileStream.Free;
exit;
end;
end;
FileStream.Free;
end;

sven

Useless Hacker
14-07-2004, 07:28 PM
You will need to call SetLength() every iteration of the loop, before the call to ReadBuffer(), even though the strings are the same length, since this guarantees that "c" is a unique string; otherwise all the values in the array will point to the same string.