Recent

Author Topic: Is there a way to seek/read/write with a text file?  (Read 678 times)

billd

  • Jr. Member
  • **
  • Posts: 51
Is there a way to seek/read/write with a text file?
« on: August 27, 2023, 04:35:38 pm »
Is there a way to seek, then read or write to a line in a text file?

The description of the seek function indicates it is not available with text files.

I tried searching but found no helpful hits (or maybe my search terms were too broad).

Thanks

Fibonacci

  • Full Member
  • ***
  • Posts: 219
  • #PDK
Re: Is there a way to seek/read/write with a text file?
« Reply #1 on: August 27, 2023, 04:54:00 pm »
Not sure I understood what you want. You want to seek in a file if you have handle type "text"? You can use GetFileHandle to get OS file handle and then seek

https://lazarus-ccr.sourceforge.io/docs//rtl/sysutils/getfilehandle.html

If you want to seek to certain line, thats not possible, you will need to check byte by byte for line endings

billd

  • Jr. Member
  • **
  • Posts: 51
Re: Is there a way to seek/read/write with a text file?
« Reply #2 on: August 27, 2023, 04:59:49 pm »
Yes, I wanted to seek to a specific line, read that line, modify the line, then write it back.

From your answer it sounds like that is not possible, at least not easily.

I have a comma delimited text file (so it can be imported into Excel) but I need to make some changes to the file.  I should have set it up as a typed file, then create an export function to export it as a text file.   

Darn, back to the drawing board.

Thanks,
 - Bill

Fibonacci

  • Full Member
  • ***
  • Posts: 219
  • #PDK
Re: Is there a way to seek/read/write with a text file?
« Reply #3 on: August 27, 2023, 05:07:18 pm »
Note also if you seek somewhere you can only overwrite data, you cant add data at the middle of the file

440bx

  • Hero Member
  • *****
  • Posts: 3625
Re: Is there a way to seek/read/write with a text file?
« Reply #4 on: August 27, 2023, 05:25:41 pm »
Darn, back to the drawing board.
What you want to do is very similar to what a "simple" text editor does.

Since you mention you're dealing with a csv file, the simple way would be to read the entire file into memory, create an index (array of pointers to lines), the index would give you the direct access you're looking for.  When a line is modified, allocate a new block of memory to hold the edited line and a second pointer in the index to that block.

This way your index has two pointers, pointer to original line, pointer to modified line (or nil if it has not been modified), that allows you to seek to any line at any time.  Saving the file can either be done by saving one line at a time (inefficient) or creating a temp block of memory that contains all the lines, unmodified and modified.  That way the entire block can be saved in a single I/O (much more efficient.)

Note that this method is fine for reasonably small files (say less than 50MB - off the cuff estimate), for larger files, something a little more sophisticated may be necessary to ensure reasonably good performance.

Obviously, while this way you get direct access to any line, this access is _not_ obtained using Pascal functions but your own.

HTH.
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 SP1 64bit.

Warfley

  • Hero Member
  • *****
  • Posts: 1469
Re: Is there a way to seek/read/write with a text file?
« Reply #5 on: August 27, 2023, 07:08:46 pm »
I have a comma delimited text file (so it can be imported into Excel) but I need to make some changes to the file.  I should have set it up as a typed file, then create an export function to export it as a text file.   

If your file is not too large simply use a TStringList and load the whole file in at once:
Code: Pascal  [Select][+][-]
  1. var
  2.   sl: TStringList;
  3. begin
  4.   sl := TStringList.Create;
  5.   try
  6.     sl.LoadFromFile(FileName);
  7.     sl[42] := NewLine42;
  8.     sl.SaveToFile(FileName);
  9.   finally
  10.     sl.Free;
  11.   end;
  12. end;

MarkMLl

  • Hero Member
  • *****
  • Posts: 6383
Re: Is there a way to seek/read/write with a text file?
« Reply #6 on: August 27, 2023, 08:17:03 pm »
Short answer: no, because records are variable-length.

The answer depends on (a) the size of the file and (b) the balance of how many times you want to read and update the same file.

I've had to hack around a lot in the past reading a large (for the timeframe) CSV or similar and using part or all of the content to generate a new file, and I did that by creating two index files: the first had a byte position for the start of each line and the second had a line position for a sort on a particular key. It worked in my case, but it won't work if you want to update the file in situ.

If you want to repeatedly update the same file in situ, then the best solution by far is to load it into a database such as SQLite: either broken up into columns or simply as one line per row (where you still have the advantage that changes in line length are accommodated automatically). Then whenever you want the content in text file dump it to a CSV.

However I'd caution here that if you find that you can dispense with the output text file and simply refer directly to the database, move from an embedded database (i.e. SQLite in the para above) to something that comfortably supports multiple clients accessing it simultaneously sooner rather than later. In particular, do not under any circumstances attempt to allow multiple client programs to access an (e.g.) SQLite database using file sharing.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

KodeZwerg

  • Hero Member
  • *****
  • Posts: 1719
  • Fifty shades of code.
    • Delphi & FreePascal
Re: Is there a way to seek/read/write with a text file?
« Reply #7 on: August 27, 2023, 09:29:19 pm »
Yes, I wanted to seek to a specific line, read that line, modify the line, then write it back.
If your file is not too large simply use a TStringList and load the whole file in at once:
Code: Pascal  [Select][+][-]
  1. var
  2.   sl: TStringList;
  3. begin
  4.   sl := TStringList.Create;
  5.   try
  6.     sl.LoadFromFile(FileName);
  7.     sl[42] := NewLine42;
  8.     sl.SaveToFile(FileName);
  9.   finally
  10.     sl.Free;
  11.   end;
  12. end;

Code: Pascal  [Select][+][-]
  1.     sl.LoadFromFile(FileName);
  2.     Insert('TextToInsert', sl[SeekLine], PositionInLine);
  3.     sl.SaveToFile(FileName);
« Last Edit: Tomorrow at 31:76:97 by KodeZwerg »

Handoko

  • Hero Member
  • *****
  • Posts: 5060
  • My goal: build my own game engine using Lazarus
Re: Is there a way to seek/read/write with a text file?
« Reply #8 on: August 28, 2023, 09:03:41 pm »
In the link below, in the "File handling" section:
https://wiki.freepascal.org/Portal:HowTo_Demos

There you can find 2 text file demos.

 

TinyPortal © 2005-2018