Recent

Author Topic: Delphi 7 handling files  (Read 2490 times)

Mark12345

  • New Member
  • *
  • Posts: 17
Delphi 7 handling files
« on: February 25, 2021, 09:18:27 am »
Hi guys i'm new with handling files and i need to know how to write read and , seek an especific position of an index array of string , the array  contains 30 slots (all of this with Tfilestream)
 

Procedure write
For i:=     to Do
Writebuffer(write the whole array)

End;

Function


Seek(position of the array lets say quest[5])
Read (quest[5])
End;


Mark12345

  • New Member
  • *
  • Posts: 17
Re: Delphi 7 handling files
« Reply #1 on: February 25, 2021, 09:31:51 am »
Readbuffer not read

lucamar

  • Hero Member
  • *****
  • Posts: 3778
Re: Delphi 7 handling files
« Reply #2 on: February 25, 2021, 09:48:40 am »
Do you need to be able to read/write the file as a text file (let's say, something editable with Notepad)?

Not that it matters much, but you (and we) need to know that.

The process is relatively straigthforward: prepare your stream and, to write, just traverse the array and write each string to it. To read just one string, prepare the stream (if not already done) or seek to the start and read each string until you reach the one you want.

The page File Handling in Pascal in the wiki can get you started on how to do it though, to be fair, it's not well thought out for beginners ...
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

Mark12345

  • New Member
  • *
  • Posts: 17
Re: Delphi 7 handling files
« Reply #3 on: February 25, 2021, 10:43:42 am »
Yes in a .txt File

Here it's something what i did

Code: Pascal  [Select][+][-]
  1. Type
  2. Tarr=array[1..4] of string;
  3. Var
  4. Arraystring:Tarr
  5.  
  6. procedure tform1.WriteToFile4(var Arraystring:Tarr);
  7. var
  8.   fs: TFileStream;
  9.  
  10.   Len1, c, i: Cardinal;
  11. begin
  12.   Memo1.lines.clear;
  13.   SetLength(arrayString, 4);
  14.   arrayString[0] := 'First string in this Array';
  15.   arrayString[1] := 'the Second Array string';
  16.   arrayString[2] := 'String number three of this Array';
  17.   arrayString[3] := 'this is the fourth String';
  18.   fs := TFileStream.Create('C:\Users\Iña\Documents\Delphi\Streamtest.txt',
  19.                  fmCreate or fmOpenWrite or fmShareDenyWrite);
  20.   try
  21.     c := Length(arrayString);
  22.     Fs.WriteBuffer(c, SizeOf(c));
  23.     for i := 0 to c-1 do begin
  24.       Len1 := Length(arrayString[i]);
  25.       fs.WriteBuffer(Len1, SizeOf(Len1));
  26.       if Len1 > 0 then begin
  27.         fs.WriteBuffer(pointer(arrayString[i])^, Len1*sizeof(char));
  28.  
  29.       end;
  30.     end;
  31.   finally
  32.     fs.free;
  33.   end;
  34.  
  35.  
  36. procedure tform1.ReadfromFile4(var Arraystring:Tarr);
  37.   var
  38.   fs: TFileStream;
  39.  
  40.   i, Len1 : Cardinal;
  41. //  s : string;
  42. begin
  43.   fs := TFileStream.Create('C:\Users\Iña\Documents\Delphi\Streamtest.txt',
  44.                  fmOpenRead or fmShareDenyWrite);
  45.   Memo1.lines.clear;
  46.  
  47.   try
  48.     fs.ReadBuffer(Len1, SizeOf(Len1));
  49.     SetLength(arrayString, Len1);
  50.     FOR i := 0 to Len1-1 do begin
  51.       fs.ReadBuffer(Len1, SizeOf(Len1));
  52.       SetLength(arrayString[i], Len1);
  53.       Fs.ReadBuffer(pointer(arrayString[i])^, Len1*sizeof(char));
  54.       memo1.lines.add (arrayString[i]);
  55.     end;
  56.   finally
  57.     fs.free;
  58.   end;
  59. end;
  60.  

Sthe code doesn't work(here im trying to write and read all but i want to read only one position) and also i don't how to use the seek, so the thing here are two things fix the code and use the seek to read only one position of the array(the information that contains the position)
« Last Edit: February 25, 2021, 11:02:01 am by Iña123 »

lucamar

  • Hero Member
  • *****
  • Posts: 3778
Re: Delphi 7 handling files
« Reply #4 on: February 25, 2021, 10:48:53 am »
You're trying to read/write the whole array at a time; instead you should be reading/writing it a string at a time.*

Allow me a little time and I'll write a small demo based on your code.


* Disregard that; the forum software parsed some of your code as BBCode. You should read here on how to post code in the forum: Forum: Use code tags
« Last Edit: February 25, 2021, 10:53:15 am by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

Mark12345

  • New Member
  • *
  • Posts: 17
Re: Delphi 7 handling files
« Reply #5 on: February 25, 2021, 10:55:57 am »
I modified my comment of the code but still doesn't work(the code in delphi)
« Last Edit: February 25, 2021, 10:58:37 am by Iña123 »

lucamar

  • Hero Member
  • *****
  • Posts: 3778
Re: Delphi 7 handling files
« Reply #6 on: February 25, 2021, 11:04:36 am »
Is there any reason why you want to use a TFileStream or any other solution would suffice?

Also, you're storing (or trying to) the length of each string along with the string itself; that can be more easily done with WriteAnsiString() and ReadAnsiString(). But then your file will not be a plain-text file. Is that really what you want?
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

Mark12345

  • New Member
  • *
  • Posts: 17
Re: Delphi 7 handling files
« Reply #7 on: February 25, 2021, 11:49:23 am »
I want to use tfilestream because i'am making a quizgame and i want to write read and , seek a random question , the array contains 30 slots which has a lot of data( one question in each slot) , the code is an example of what i was trying to do
It doesn' t matter if it's .txt .dat or whatever
Tfilestream with writebuffer readbuffer is faster and more efficient than blockread blockwrite for a lot of data.
« Last Edit: February 25, 2021, 11:51:53 am by Iña123 »

lucamar

  • Hero Member
  • *****
  • Posts: 3778
Re: Delphi 7 handling files
« Reply #8 on: February 25, 2021, 12:02:39 pm »
OK, here is the promised example code ...

Let's say this is the test code you want working:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. const
  3.   filename = 'C:\Users\Joe\Documents\Delphi\Streamtest.tst';
  4. var
  5.   TheStrings: TStringArray;
  6. begin
  7.   {Set string array}
  8.   SetLength(TheStrings, 4);
  9.   TheStrings[0] := 'First string in this Array';
  10.   TheStrings[1] := 'the Second Array string';
  11.   TheStrings[2] := 'String number three of this Array';
  12.   TheStrings[3] := 'this is the fourth String';
  13.   {Write it}
  14.   WriteToFile(Filename, TheStrings);
  15.   { Reset the array}
  16.   SetLength(TheStrings, 0);
  17.   {Read it back and show it}
  18.   TheStrings := ReadfromFile(filename);
  19.   if Length(TheStrings) > 0  then begin
  20.     Memo1.Lines.Clear;
  21.     Memo1.Lines.AddStrings(TheStrings);
  22.   end;
  23.   {Now read and show only line 2}
  24.   Memo1.Lines.Add('Reading line no. 2: ');
  25.   Memo1.Lines.Add(ReadfromFile(filename, 2));
  26. end;

WriteToFile() would be something like:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.WriteToFile(const Filename: String; Strings: TStringArray);
  2. var
  3.   fs: TFileStream;
  4.   c: Cardinal;
  5.   sv: String;
  6. begin
  7.   try
  8.     if FileExists(Filename) then
  9.       fs := TFileStream.Create(Filename, fmOpenWrite or fmShareDenyWrite)
  10.     else
  11.       fs := TFileStream.Create(Filename, fmCreate);
  12.     {Write the strings to the file}
  13.     try
  14.       c := Length(Strings);
  15.       fs.WriteDWord(c);
  16.       for sv in Strings do
  17.         fs.WriteAnsiString(sv);
  18.     finally
  19.       fs.free;
  20.     end;
  21.   except
  22.     on EFOpenError do
  23.       ShowMessage('Unable to create or write to:' + LineEnding + Filename);
  24.   end;
  25. end;

And the two "versions" (overloads) of ReadfromFile() would be:
Code: Pascal  [Select][+][-]
  1. function TForm1.ReadfromFile(const Filename: String): TStringArray;
  2. {This overload reads and returns the whole array.
  3.  NOTE: The caller is responsible of the array's destruction, if needed}
  4. var
  5.   fs: TFileStream;
  6.   c, i: Cardinal;
  7. begin
  8.   Result := Default(TStringArray);
  9.   if not FileExists(Filename) then
  10.     ShowMessage('Unable to read from'+ LineEnding + Filename)
  11.   else begin
  12.     fs := TFileStream.Create(Filename, fmOpenRead or fmShareDenyWrite);
  13.     try
  14.       c := fs.ReadDWord;
  15.       SetLength(Result, c);
  16.       for i := 0 to c-1 do
  17.         Result[i] := fs.ReadAnsiString;
  18.     finally
  19.       fs.free;
  20.     end;
  21.   end;
  22. end;
  23.  
  24. function TForm1.ReadfromFile(const Filename: String; Index: Integer): String;
  25. {This overload reads and returns string no. Index (0-based)}
  26. var
  27.   fs: TFileStream;
  28.   c, i: Cardinal;
  29.   sv: String;
  30. begin
  31.   Result := '';
  32.   if not FileExists(Filename) then
  33.     ShowMessage('Unable to read from'+ LineEnding + Filename)
  34.   else begin
  35.     fs := TFileStream.Create(Filename, fmOpenRead or fmShareDenyWrite);
  36.     try
  37.       c := fs.ReadDWord;
  38.       if c <= Index then
  39.         ShowMessageFmt(
  40.             'Requested line %d but only %d lines in file', [Index, c])
  41.       else begin
  42.         {Brute-force approach, but we are dealing with strings ...}
  43.         for i := 0 to Index do
  44.           sv := fs.ReadAnsiString;
  45.         Result := sv;
  46.       end;
  47.     finally
  48.       fs.free;
  49.     end;
  50.   end;
  51. end;

Note that since we are dealing with variable length strings you can't really use seek without complicating the code quite a little, though it can (and should) be done if there are lots of strings (on the tens of thousands or more); you have only about 30 so no problem with the brute-force approach ;)

Also, this is just an example so I've left out most of the error-checking: you should add it where appropiate for real production.

One last thing: I've only tested that it compiles cleanly, not whether it works (though it should).

ETA: For just 30 questions, even if they are long, what I would do would be to use a TStringList; once read from the file it's simplicity itself to access any line you want, and reading/writing it from/to a file is just a one-liner.
« Last Edit: February 25, 2021, 12:09:09 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

Handoko

  • Hero Member
  • *****
  • Posts: 4158
  • My goal: build my own game engine using Lazarus
Re: Delphi 7 handling files
« Reply #9 on: February 25, 2021, 12:06:32 pm »
@Iña123

Have you consider using TextFile? I don't mean it is better but it is really easier than using TFileStream. If you're interested to see how to use TextFile, try these demos:

https://forum.lazarus.freepascal.org/index.php/topic,37766.msg254800.html#msg254800
https://forum.lazarus.freepascal.org/index.php/topic,39769.msg274036.html#msg274036

Tfilestream with writebuffer readbuffer is faster and more efficient than blockread blockwrite for a lot of data.

For the case of a lot of data, you should consider using a database or at least TDBF.

winni

  • Hero Member
  • *****
  • Posts: 2289
Re: Delphi 7 handling files
« Reply #10 on: February 25, 2021, 05:06:26 pm »
Hi!

If you dont like a stream and a DB seems to be too big for your needs, then there is a weird solution:

Code: Pascal  [Select][+][-]
  1. type string80 = string[80];
  2.  
  3. var F : file of string80;
  4.  
Now you can do a random acces like in any other file:
Code: Pascal  [Select][+][-]
  1. var s : string;
  2.  
  3. ....
  4. assignFile (F, './MyText.txt');
  5. reset (F);
  6. seek (F,3);
  7. read(F,s);
  8. ShowMessage ('String #3  is ' +s);
  9. closeFile(F);
  10. .....
  11.  

Take care: Never try to edit a file like this with an editor - you will crash the structure. Read only is allowed.

Writing to this kind of file is only allowed through the above shown structure.

Not such a marvelous solution.

What amount of strings are we talking about?
You could use (or misstreat) the IniFiles unit and store the strings in an IniFile.

Winni

Mark12345

  • New Member
  • *
  • Posts: 17
Re: Delphi 7 handling files
« Reply #11 on: February 25, 2021, 06:59:34 pm »
Yeah, i think i should use tstringlist if you guys say that seek with tfilestream is dificult
But in the net there is less information about tstringlist than tfilestream
I don't know i'm screwed

There isn't nothing similar to write the whole unfixed array of string (array[1..30] of string) , seek a slot lets say i seek (question[5]) and then read it



Handoko

  • Hero Member
  • *****
  • Posts: 4158
  • My goal: build my own game engine using Lazarus
Re: Delphi 7 handling files
« Reply #12 on: February 25, 2021, 07:09:57 pm »
... seek a slot lets say i seek (question[5]) and then read it

It seems you didn't try the demo I gave you. It really allows you to seek any line you want.

And what about Lucamar's code? Have you tried it? It should work. To me, TStringList is easier than TFileStream.
« Last Edit: February 25, 2021, 07:12:14 pm by Handoko »

lucamar

  • Hero Member
  • *****
  • Posts: 3778
Re: Delphi 7 handling files
« Reply #13 on: February 25, 2021, 07:16:05 pm »
With a TStringList you would do:

to write the file,
Code: Pascal  [Select][+][-]
  1. AStrList.SaveToFile('some/file/name');

to read the file:
Code: Pascal  [Select][+][-]
  1. AStrList.LoadFromFile('some/file/name')

to add strings to the list:
Code: Pascal  [Select][+][-]
  1. AStrList.Add('Some string');
  2. {or, to put it at some position,}
  3. AStrList.Insert(Index, 'SomeString');

finally, to retrieve some string,
Code: Pascal  [Select][+][-]
  1. SomeString := AStrList[index];

There is really little to write about TStringList other than the obvious and that is fairly well covered by the documentation. It can be thought of (very, very basically) as an array of strings with quite a few extra methods to handle the most common operations one would want.
« Last Edit: February 25, 2021, 07:20:47 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

Mark12345

  • New Member
  • *
  • Posts: 17
Re: Delphi 7 handling files
« Reply #14 on: February 25, 2021, 07:58:56 pm »
maybe the code wasn´t working because it´s an unfixed array
(the write and read you posted)
(i put the same information in  the slots of the  array so i don't have to waste time writing something diferent)
 
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7.   Dialogs, StdCtrls;
  8.  
  9. type
  10.   TForm1 = class(TForm)
  11.     Button1: TButton;
  12.     procedure Button1Click(Sender: TObject);
  13.   private
  14.     { Private declarations }
  15.   public
  16.     { Public declarations }
  17.   end;
  18.  
  19. var
  20.   Form1: TForm1;
  21.  
  22. implementation
  23. const
  24. n=30;
  25.  
  26. type
  27. Tstringarray= array[1..n] of string;
  28. var
  29. TheStrings: TStringArray;
  30.  
  31. {$R *.dfm}
  32.  
  33.  
  34.  
  35. procedure    load(var TheStrings: TStringArray);
  36. var
  37. i:integer;
  38. begin
  39.  
  40.   TheStrings[1] := 'First string in this Array';
  41.   TheStrings[2] := 'the Second Array string';
  42.   TheStrings[3] := 'String number three of this Array';
  43.   TheStrings[4] := 'this is the fourth String';
  44.   TheStrings[5] := 'First string in this Array';
  45.   TheStrings[6] := 'the Second Array string';
  46.   TheStrings[7] := 'String number three of this Array';
  47.   TheStrings[8] := 'this is the fourth String';
  48.   TheStrings[9] := 'First string in this Array';
  49.   TheStrings[10] := 'the Second Array string';
  50.   TheStrings[11] := 'String number three of this Array';
  51.   TheStrings[12] := 'this is the fourth String';
  52.   TheStrings[13] := 'First string in this Array';
  53.   TheStrings[14] := 'the Second Array string';
  54.   TheStrings[15] := 'String number three of this Array';
  55.   TheStrings[16] := 'this is the fourth String';
  56.   TheStrings[17] := 'First string in this Array';
  57.   TheStrings[18] := 'the Second Array string';
  58.   TheStrings[19] := 'String number three of this Array';
  59.   TheStrings[20] := 'this is the fourth String';
  60.   TheStrings[21] := 'the Second Array string';
  61.   TheStrings[22] := 'String number three of this Array';
  62.   TheStrings[23] := 'this is the fourth String';
  63.   TheStrings[24] := 'First string in this Array';
  64.   TheStrings[25] := 'the Second Array string';
  65.   TheStrings[26] := 'String number three of this Array';
  66.   TheStrings[27] := 'this is the fourth String';
  67.   TheStrings[28] := 'First string in this Array';
  68.   TheStrings[29] := 'the Second Array string';
  69.   TheStrings[30] := 'String number three of this Array';
  70.  
  71.   for i:=1 to n do
  72.    begin
  73.    showmessage(TheStrings[i]);
  74.    end;
  75. end;
  76.  
  77.  
  78.  
  79.  
  80.  
  81.  
  82. procedure TForm1.Button1Click(Sender: TObject);
  83. var
  84. TheStrings: TStringArray;
  85. begin
  86. load(TheStrings);
  87. end;
  88.  
  89. end.
  90.  
  91.  
« Last Edit: February 25, 2021, 08:01:16 pm by Iña123 »

 

TinyPortal © 2005-2018