Recent

Author Topic: [SOLVED] Write/Read to a file with specific x and y coordinates  (Read 8350 times)

DiCri

  • Full Member
  • ***
  • Posts: 151
  • My goal : Build a game
    • http://manueldicriscito.altervista.org/DinoLand.zip
[SOLVED] Write/Read to a file with specific x and y coordinates
« on: September 12, 2016, 11:34:58 pm »
Hi guys, i'd like to know if is it possible to write or read the file with x and y coords ..
I use this:
Code: Pascal  [Select][+][-]
  1. var
  2.   data : textfile;
  3.   i : integer;
  4.   directory : string;
  5. begin
  6.  ...
  7. Assign(Data, Directory );
  8. Reset(Data);
  9. Readln(Data, I );
  10. Close(Data);
  11. ...
  12. end.
  13.  

Imagine the file contains three lines with three numbers and i want to read only the second line and not the first
Can i do that without creatig other variables?
« Last Edit: September 18, 2016, 06:07:53 pm by Manu12x »
I'm a game developer.. Now studying..
Go download my game:
http://manueldicriscito.altervista.org/DinoLand.zip

lainz

  • Hero Member
  • *****
  • Posts: 3709
  • Leandro Diaz
Re: Write/Read to a file with specific x and y coordinates
« Reply #1 on: September 13, 2016, 12:45:54 am »
Use a TStringList.

Code: Pascal  [Select][+][-]
  1. var
  2.   s: TStringList;
  3. begin
  4.   // save
  5.   s := TStringList.Create;
  6.   s.Add('first line');
  7.   s.Add('second line');
  8.   s.Add('third line');
  9.   s.SaveToFile('file.txt');
  10.   s.Free;
  11.  
  12.   // load
  13.   s := TStringList.Create;
  14.   s.LoadFromFile('file.txt');
  15.   writeln(s[1]); // second line
  16.   s.Free;
  17. end;    

if you need to read many integers separated by spaces in the same line you can create a secondary stringlist.

Code: Pascal  [Select][+][-]
  1. s2 := TStringList.Create;
  2. s2.CommaText := s[1];

then you can acces each element from that line
Code: Pascal  [Select][+][-]
  1. s2[0] // first number
  2. s2[1] // second number
« Last Edit: September 13, 2016, 02:31:11 am by lainz »

wp

  • Hero Member
  • *****
  • Posts: 7551
Re: Write/Read to a file with specific x and y coordinates
« Reply #2 on: September 13, 2016, 12:56:19 am »
Imagine the file contains three lines with three numbers and i want to read only the second line and not the first
Can i do that without creatig other variables?
When reading the frist line don't specify any variable for the read input; this way this line will be discarded:
Code: Pascal  [Select][+][-]
  1. var
  2.   data: textfile;
  3.   i: integer;
  4. begin
  5.   AssignFile(Data, 'd:\test.txt');
  6.   Reset(Data);
  7.   Readln(Data);     // Read first line, but dispose result
  8.   ReadLn(Data, I);  // Read second line, store value in variable I
  9.   WriteLn(I);       // Just for a test: write out the value read
  10.   CloseFile(Data);
  11. end.
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

Angus

  • New Member
  • *
  • Posts: 16
Re: Write/Read to a file with specific x and y coordinates
« Reply #3 on: September 13, 2016, 12:58:49 am »
Hi

The TStringList approach will work very well until the file is large, then loading into the list will cause a noticeable performance hit.  Generally unless some prior knowledge is available regarding the location of the data in the file there is no choice but to 'scan' the file first to establish some basic information, not least of which would be to determine the number of lines; this would of course imply 'creating other variables'.
For rapid access to a specific line(s) of the file it may be appropriate to use a database table and take advantage of the speed improvements afforded by use of an index.  Again there would be an additional variable introduced in the form of a table, but there-on-in retrieving data would be efficient. For large files memory management headaches would fall to the database engine to manage.

lainz

  • Hero Member
  • *****
  • Posts: 3709
  • Leandro Diaz
Re: Write/Read to a file with specific x and y coordinates
« Reply #4 on: September 13, 2016, 01:05:41 am »
Please he is a newby, give him a code that he can run like I did.

Manu, if the file is not big, it will load faster anyway try it yourself.

lainz

  • Hero Member
  • *****
  • Posts: 3709
  • Leandro Diaz
Re: Write/Read to a file with specific x and y coordinates
« Reply #5 on: September 13, 2016, 01:10:26 am »
Try this application, it takes a second or less to save and load 1Million integers:

How many you need for your game?

Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. uses
  4.   Classes, SysUtils;
  5. var
  6.   s: TStringList;
  7.   i, j: integer;
  8.  
  9. begin
  10.   s := TStringList.Create;
  11.   for i:=1 to 1000000 do
  12.   begin
  13.     s.Add(IntToStr(i));
  14.   end;
  15.   s.SaveToFile('file.txt');
  16.   s.Free;
  17.  
  18.   s := TStringList.Create;
  19.   s.LoadFromFile('file.txt');
  20.   for i:=0 to s.Count-1 do
  21.   begin
  22.     j := StrToInt(s[i]);
  23.   end;
  24.   s.Free;
  25.   writeln('done');
  26.   readln();
  27. end.  
« Last Edit: September 13, 2016, 01:38:51 am by lainz »

DiCri

  • Full Member
  • ***
  • Posts: 151
  • My goal : Build a game
    • http://manueldicriscito.altervista.org/DinoLand.zip
Re: Write/Read to a file with specific x and y coordinates
« Reply #6 on: September 13, 2016, 06:15:40 am »
Hey guys, i mean like gotoxy(x,y); but not on screen but while reading or writing to a file.
File readed is < of 100KB.. Nothing more.. Only 10 integers
I'm a game developer.. Now studying..
Go download my game:
http://manueldicriscito.altervista.org/DinoLand.zip

DiCri

  • Full Member
  • ***
  • Posts: 151
  • My goal : Build a game
    • http://manueldicriscito.altervista.org/DinoLand.zip
Re: Write/Read to a file with specific x and y coordinates
« Reply #7 on: September 13, 2016, 06:41:16 am »
Try this application, it takes a second or less to save and load 1Million integers:

How many you need for your game?

Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. uses
  4.   Classes, SysUtils;
  5. var
  6.   s: TStringList;
  7.   i, j: integer;
  8.  
  9. begin
  10.   s := TStringList.Create;
  11.   for i:=1 to 1000000 do
  12.   begin
  13.     s.Add(IntToStr(i));
  14.   end;
  15.   s.SaveToFile('file.txt');
  16.   s.Free;
  17.  
  18.   s := TStringList.Create;
  19.   s.LoadFromFile('file.txt');
  20.   for i:=0 to s.Count-1 do
  21.   begin
  22.     j := StrToInt(s[i]);
  23.   end;
  24.   s.Free;
  25.   writeln('done');
  26.   readln();
  27. end.  
Hey lainz i didn't know about TStringList but it's so simple as i see! Thank you but what's s.Count?
And if i want to write an integer = 450 then s[1] is 450 or 4??
I'm a game developer.. Now studying..
Go download my game:
http://manueldicriscito.altervista.org/DinoLand.zip

lainz

  • Hero Member
  • *****
  • Posts: 3709
  • Leandro Diaz
Re: Write/Read to a file with specific x and y coordinates
« Reply #8 on: September 13, 2016, 04:18:19 pm »
s.Count is the ammount of items in the string list, the ammount of lines.

If you want to write an integer you need to store it as string

Code: Pascal  [Select][+][-]
  1. var
  2.   num: integer;
  3.  
  4. s.Add(IntToStr(num));

to read it convert it to number back

Code: Pascal  [Select][+][-]
  1. num := StrToInt(s[1]);

DiCri

  • Full Member
  • ***
  • Posts: 151
  • My goal : Build a game
    • http://manueldicriscito.altervista.org/DinoLand.zip
Re: Write/Read to a file with specific x and y coordinates
« Reply #9 on: September 13, 2016, 04:37:25 pm »
i solved :
Code: Pascal  [Select][+][-]
  1.  
  2. var
  3.   OptionsStr : TStringList;
  4.   State : Integer;
  5. begin
  6. ...
  7. if FileExists('Data\Options.txt' ) then
  8.   begin
  9.     OptionsStr := TStringList.Create;
  10.     OptionsStr.LoadFromFile('Data\Options.txt' );
  11.     State := StrToInt(OptionsStr[0]);
  12.    ... // here there are some functions that maybe can change value of variable "state".
  13.     OptionsStr[0] := IntToStr( State );
  14.     OptionsStr.SaveToFile('Data\Options.txt' );
  15.   end;
  16. ...
  17. end;
  18.    
  19.  
That works correctly! Thanks! But maybe i should learn how to write and read data from files.. i see some games read data from a file wich contains unreadable chars! I don't know if i should use BlockWrite and BlockRead.. i don't understand them very well as i read in documentation.. thanks again
« Last Edit: September 13, 2016, 04:42:26 pm by Manu12x »
I'm a game developer.. Now studying..
Go download my game:
http://manueldicriscito.altervista.org/DinoLand.zip

wp

  • Hero Member
  • *****
  • Posts: 7551
Re: Write/Read to a file with specific x and y coordinates
« Reply #10 on: September 13, 2016, 04:40:07 pm »
Hey guys, i mean like gotoxy(x,y); but not on screen but while reading or writing to a file.
File readed is < of 100KB.. Nothing more.. Only 10 integers
You are using a text file. Since the line length can vary there is no possibility to "goto" to some predefined line. You must declare the file such that it consits of records of predefined length (http://wiki.freepascal.org/File_Handling_In_Pascal). Then you can "seek" for a record at a given index. But note that index numbers begin with zero!
 
Here's an example. For simplicity i assume that your file consists of "integers". Declare the file variable as a "file of integer". Now the reading/writing process accesses the file in blocks of 4 bytes because an integer is 4 bytes large. To seek a particular number you must know its index, like in an array. Since the index begins at 0 you must specify the index 1 if you seek for the second number. Note that there is no "ReadLn" or "WriteLn" for binary files because they don't contain "lines".
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. var
  6.   data : file of integer;
  7.   i : integer;
  8. begin
  9.   Assign(Data, 'd:\test.dat');
  10.  
  11.   // Just prepare some dummy file
  12.   Rewrite(Data);
  13.   for i:=1 to 10 do
  14.     Write(Data, i);
  15.   CloseFile(Data);
  16.  
  17.   // Open the file for reading
  18.   Reset(Data);
  19.   // Read the second number
  20.   // Go to the second number, it has index 1 because index number begin at zero.
  21.   Seek(Data, 1);  
  22.   // Read one integer here to the variable I
  23.   Read(Data, I);
  24.   // Close the file
  25.   CloseFile(Data);
  26.  
  27.   // Write out the found result to the console
  28.   // According to what was written to the file the second number should have the value 2
  29.   WriteLn(I);
  30.  
  31.   ReadLn;
  32. end.
« Last Edit: September 13, 2016, 04:43:42 pm by wp »
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

lainz

  • Hero Member
  • *****
  • Posts: 3709
  • Leandro Diaz
Re: Write/Read to a file with specific x and y coordinates
« Reply #11 on: September 13, 2016, 04:43:15 pm »
These files are binary files not text files :)

Here you go:
http://www.delphibasics.co.uk/Article.asp?Name=Files

Scroll down until 'Reading and writing to typed binary files' or 'Reading and writing to pure binary files' as you say it uses BlockRead and BlockWrite.

DiCri

  • Full Member
  • ***
  • Posts: 151
  • My goal : Build a game
    • http://manueldicriscito.altervista.org/DinoLand.zip
Re: Write/Read to a file with specific x and y coordinates
« Reply #12 on: September 13, 2016, 05:18:06 pm »
Hey guys, i mean like gotoxy(x,y); but not on screen but while reading or writing to a file.
File readed is < of 100KB.. Nothing more.. Only 10 integers
You are using a text file. Since the line length can vary there is no possibility to "goto" to some predefined line. You must declare the file such that it consits of records of predefined length (http://wiki.freepascal.org/File_Handling_In_Pascal). Then you can "seek" for a record at a given index. But note that index numbers begin with zero!
 
Here's an example. For simplicity i assume that your file consists of "integers". Declare the file variable as a "file of integer". Now the reading/writing process accesses the file in blocks of 4 bytes because an integer is 4 bytes large. To seek a particular number you must know its index, like in an array. Since the index begins at 0 you must specify the index 1 if you seek for the second number. Note that there is no "ReadLn" or "WriteLn" for binary files because they don't contain "lines".
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. var
  6.   data : file of integer;
  7.   i : integer;
  8. begin
  9.   Assign(Data, 'd:\test.dat');
  10.  
  11.   // Just prepare some dummy file
  12.   Rewrite(Data);
  13.   for i:=1 to 10 do
  14.     Write(Data, i);
  15.   CloseFile(Data);
  16.  
  17.   // Open the file for reading
  18.   Reset(Data);
  19.   // Read the second number
  20.   // Go to the second number, it has index 1 because index number begin at zero.
  21.   Seek(Data, 1);  
  22.   // Read one integer here to the variable I
  23.   Read(Data, I);
  24.   // Close the file
  25.   CloseFile(Data);
  26.  
  27.   // Write out the found result to the console
  28.   // According to what was written to the file the second number should have the value 2
  29.   WriteLn(I);
  30.  
  31.   ReadLn;
  32. end.
ok but :
Code: Pascal  [Select][+][-]
  1. Rewrite( Data );
  2.  
this will delete all that the file contains because it's made for writing from beginning!  Thanks i only needed of "seek" as i see.
I just want to substitute a line of the file with another integer.. ok try to see that code from my DinoLand game with SDL2 library:
Code: Pascal  [Select][+][-]
  1. ...
  2. procedure SDL_WriteCheckBox( Name : String; x, y : integer; Number : integer );
  3.   var
  4.     Rect : PSDL_Rect;
  5.     Clip : PSDL_Rect;
  6.     State : Integer;
  7.   begin
  8.   new( Rect );
  9.   new( Clip );
  10.  
  11.   ... // here i change value of Rect and clip variables
  12.  
  13.   if FileExists(' Data\Options.txt' ) then
  14.   begin
  15.   Assign( Data, GetCurrentDir + '\' + 'Data\Options.txt' );
  16.   Reset( Data );
  17.   // Here i should read integers ( data ) from the file and variable "Number" indicates the line of the file to read.
  18.   // So i don't know why.. i'll try with Seek();
  19.   // Here the variable "State" should take the value of the second line of the file.
  20.   Close( Data );
  21.   end;
  22.  
  23. ...
  24. // After determinating "State" value, the CheckBox i want to create should be active when State = 1 and not active when State = 0 ( i already know how to do this part )
  25. // Here, this variable may will change, ( depends on mouse events )
  26. ...
  27.  
  28.   Assign( Data, GetCurrentDir + '\' + Data\Options.txt );
  29.   // Rewrite( Data );    
  30.   Writeln( Data, State );
  31.   Close( Data );
  32. ..
  33. end;
  34.  
  35. begin
  36. repeat
  37.   SDL_WriteCheckBox('show fps', 300, 50, 2 ); // name of the checkbox is 'show fps', x and y positions are 300 and 50, and '2' is the line i'd like to read State.
  38. until done;
  39. end.
  40.  
Options.txt is that:
Code: Pascal  [Select][+][-]
  1. 0
  2. 0
  3. 0
  4. 0
  5.  
I just want to substitute the second line with the integer updated.. I hope you will understand me.. thanks... :-\

« Last Edit: September 13, 2016, 05:36:46 pm by Manu12x »
I'm a game developer.. Now studying..
Go download my game:
http://manueldicriscito.altervista.org/DinoLand.zip

Handoko

  • Hero Member
  • *****
  • Posts: 3765
  • My goal: build my own game engine using Lazarus
Re: Write/Read to a file with specific x and y coordinates
« Reply #13 on: September 13, 2016, 05:42:58 pm »
I do not read this thread from top to end.

But to answers your question, you can't just modify some data from certain position to certain position in the file easily, except you're using a database library, which they will do the complicated things in background.

One of the ways to do it is read all of them to memory, modify them in the memory and write them all back to file. Database will work smarter because they will use caching technology to speed up the all the processes.

I do not play a lot with database nor file. But I ever write my modules to handle this headache problems, and now I just use it without need to write it from zero. This is what it will do:

To substitute line no 3 with new data

1. Open File_Source for reading and open File_Target for writing
2. Repeat
3.    Read a new line of data from File_Source
4.    If now is line 3 then write new data to File_Target
5.    If now is not line 3 then write the old data to File_Target
6. Until it reach end of file
7. Close File_Source and Close File_Target

As I already mentioned I'm not good in file/database manipulation, some experts will give you better explanations.

lainz already give a good link. But this one is good too:
http://wiki.freepascal.org/File_Handling_In_Pascal
« Last Edit: September 13, 2016, 05:56:25 pm by Handoko »

wp

  • Hero Member
  • *****
  • Posts: 7551
Re: Write/Read to a file with specific x and y coordinates
« Reply #14 on: September 13, 2016, 06:50:15 pm »
ok but :
Code: Pascal  [Select][+][-]
  1. Rewrite( Data );
  2.  
this will delete all that the file contains because it's made for writing from beginning! 
Surely - this code is only needed by the example to get a file to work on.

I just want to substitute a line of the file with another integer.
If this file is a text file (what I suspect from the extension ".txt" in your code sample) then you are out of luck. Read the entire file into a string list, as lainz suggested - this is really very fast, believe me, you won't notice it. And then you have all the strings in the list ready for manipulation and re-saving.

If this file is a binary file of - say - integers like in my previous example you certainly can edit a value in the file if the file is opened for reading and writing. You only must know that after every reading/writing process the file pointer advances to the next file item. This means: if you read index 1 the file will point to index 2 afterwards. Therefore you must call Seek again to go back to the index that you want to change.

This example works:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. var
  6.   data : file of integer;
  7.   i : integer;
  8. begin
  9.   Assign(Data, 'd:\test.dat');
  10.  
  11.   // Just prepare some dummy file
  12.   Rewrite(Data);
  13.   for i:=1 to 10 do
  14.     Write(Data, i);
  15.   CloseFile(Data);
  16.  
  17.   // Open the file for reading and writing
  18.   FileMode := 2;  // you can skip this - this is the default anyway. It prepares a binary file for read and write access.
  19.   Reset(Data);
  20.  
  21.   // Read the second number
  22.  
  23.   // Go to the second number, it has index 1 because index numbers begin at zero.
  24.   Seek(Data, 1);
  25.   // Read one integer here to the variable I
  26.   Read(Data, I);
  27.   // Write number to console: it should show "2"
  28.   WriteLn(I);
  29.  
  30.   // Alter the number at index 1
  31.  
  32.   // Go back to index 1
  33.   Seek(Data, 1);
  34.   // Write new value
  35.   Write(Data, 100);
  36.  
  37.   // Read what's at index 1 now
  38.  
  39.   // go back to index 1
  40.   Seek(Data, 1);
  41.   // Read value
  42.   Read(Data, I);
  43.   // Write to console - it should show "100"
  44.   WriteLn(I);
  45.  
  46.   // Close the file
  47.   CloseFile(Data);
  48.  
  49.   ReadLn;
  50. end.
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

 

TinyPortal © 2005-2018