Recent

Author Topic: How to read a delimited text file, row by row, col by col?  (Read 1091 times)

Jvan

  • Full Member
  • ***
  • Posts: 181
How to read a delimited text file, row by row, col by col?
« on: January 28, 2021, 09:45:37 pm »
I have a text file, in which each line is divided into "columns" by "|". I need to handle each "cell". Please, how to?

wp

  • Hero Member
  • *****
  • Posts: 11916
Re: How to read a delimited text file, row by row, col by col?
« Reply #1 on: January 28, 2021, 10:09:46 pm »
There are several ways...

I normally read the file into a TStringlist which contains each line as a separate item. Then I apply the Split string helper to each item: When it has the '|' as parameter the string is split accordingly.

Untested:
Code: Pascal  [Select][+][-]
  1. procedure Readfile(AFileName: String);
  2. var
  3.   List: TStringList;
  4.   i: Integer;
  5.   line: String;
  6.   sa: TStringArray;
  7. begin
  8.   List := TStringList.Create;
  9.   try
  10.     List.LoadFromFile(AFileName);
  11.     for i := 0 to List.Count-1 do
  12.     begin
  13.       line := List[i];
  14.       sa := line.Split('|');
  15.       for j := 0 to High(sa) do
  16.         WriteLn ('Line ', i, ', cell ', j, ': ', sa[j]);
  17.     end;
  18.   finally
  19.     List.Free;
  20.   end;
  21. end;[code]
  22.   The

ASerge

  • Hero Member
  • *****
  • Posts: 2242
Re: How to read a delimited text file, row by row, col by col?
« Reply #2 on: January 28, 2021, 10:37:30 pm »
Code: Pascal  [Select][+][-]
  1.         WriteLn ('Line ', i, ', cell ', j, ': ', sa[j]);
If you don't need indexes, you can use a simplified syntax:
Code: Pascal  [Select][+][-]
  1. procedure ReadFile(const AFileName: String);
  2. var
  3.   List: TStringList;
  4.   Cell, Line: string;
  5. begin
  6.   List := TStringList.Create;
  7.   try
  8.     List.LoadFromFile(AFileName);
  9.     for Line in List do
  10.     begin
  11.       for Cell in Line.Split('|') do
  12.         WriteLn(Cell);
  13.     end;
  14.   finally
  15.     List.Free;
  16.   end;
  17. end;

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: How to read a delimited text file, row by row, col by col?
« Reply #3 on: January 29, 2021, 01:03:12 am »
My version, maybe poster is looking for a  class to do this ?
here is a concept class and it really compiles !  :o

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
  9.  
  10. type
  11.   TStringCells = Class(TstringList)
  12.     Private
  13.     Function fGetCell(X,Y:Integer):String;
  14.     Public
  15.     Property Cells[x,y:integer]:String read fGetCell;
  16.   end;
  17.  
  18.   { TForm1 }
  19.  
  20.   TForm1 = class(TForm)
  21.     Button1: TButton;
  22.     procedure Button1Click(Sender: TObject);
  23.   private
  24.  
  25.   public
  26.  
  27.   end;
  28.  
  29. var
  30.   Form1: TForm1;
  31.  
  32. implementation
  33.  
  34. {$R *.lfm}
  35.  
  36. { TForm1 }
  37.  
  38. procedure TForm1.Button1Click(Sender: TObject);
  39. var
  40.   FileOfCells:TStringCells;
  41. begin
  42.   FileofCells := TStringCells.Create;
  43.   FileOfCells.LoadFromFile('A File Name');
  44.   Caption := FileofCells.Cells[0,1];// just a junk test;
  45.   FileOfCells.Free;
  46. end;
  47.  
  48. Function TStringCells.fGetCell(X,Y:integer):String;
  49. var
  50.   S:Array of string;
  51. Begin
  52.   {$PUSH}
  53.   {$R+} //Force range check
  54.   S := Strings[Y].Split('|');
  55.   Result := S[X];
  56.   {$Pop}
  57. end;
  58.  
  59. end.
  60.  
  61.  
The only true wisdom is knowing you know nothing

PascalDragon

  • Hero Member
  • *****
  • Posts: 5481
  • Compiler Developer
Re: How to read a delimited text file, row by row, col by col?
« Reply #4 on: January 29, 2021, 01:21:45 pm »
I have a text file, in which each line is divided into "columns" by "|". I need to handle each "cell". Please, how to?

If you want to use dataset like processing you can use TCSVDataset and change the CSVOptions.Delimiter property:

Code: Pascal  [Select][+][-]
  1. {$mode objfpc}{$H+}
  2.  
  3. uses
  4.   csvdataset;
  5.  
  6. var
  7.   ds: TCSVDataset;
  8. begin
  9.   ds := TCSVDataset.Create(Nil);
  10.   try
  11.     ds.CSVOptions.Delimiter := '|';
  12.  
  13.     ds.LoadFromCSVFile(ParamStr(1));
  14.  
  15.     ds.Active := True;
  16.     while not ds.Eof do begin
  17.       // process each row
  18.  
  19.       ds.Next;
  20.     end;
  21.   finally
  22.     ds.Free;
  23.   end;
  24. end.

AL

  • Sr. Member
  • ****
  • Posts: 264
Re: How to read a delimited text file, row by row, col by col?
« Reply #5 on: January 29, 2021, 10:56:12 pm »
Another option:

You can also load it to a stringgrid with

Stringgrid1.LoadFromCSVFile(fName,'|',false,0,true);

//  Stringgrid1.LoadFromCSVFile(fName,'Delimiter',UseTitles,FromLine,Skip empty lines); 

Then you can work your items with row, colums indexes.
         
Laz 3.1, fpc 3.2.2, Win10
Laz 3.1  fpc 3.2.2, MacOS Monterey running on VMWare/Win 10
Laz 3.1  fpc 3.2.2 Ubuntu 20.04

egsuh

  • Hero Member
  • *****
  • Posts: 1289
Re: How to read a delimited text file, row by row, col by col?
« Reply #6 on: January 30, 2021, 07:23:06 am »

Using array of array.. not tested.

Code: Pascal  [Select][+][-]
  1. const
  2.    filename = 'c:\test\testfile.txt';
  3. var
  4.    items: array of array of string;
  5.    Delimiter: Char='|';
  6.    f: textfile;
  7.    s: string;
  8. begin
  9.    AssignFile(f, filename);
  10.    Reset(f),
  11.    while not eof(f) do begin
  12.        readln(f, s)
  13.        items += [s.split(Delimiter)];
  14.    end;
  15.    CloseFile(f);  
  16. end;

 

TinyPortal © 2005-2018