1

Here is my code.

var
  filehan : Textfile;
  i : Integer;
  LineOfText   : String;
  tsl : TStringList;
  Name, Emp_id : string;
begin
  stf := TStringList.create;
  Assignfile ( filehan, 'EMP.txt');
  Reset ( filehand );
  While not EOF(filehan) do
  begin
    inc(i);
    ReadLn  ( filehan, LineOfText );
    tsl :=substrings(LineOfText, ':' );
    Name := tsl[1];
    Emp_id := tsl[0];

    tsl.SaveToFile('FSTRING.txt');
  end;

  CloseFile (FFile);
end;

function SubStrings(AString: String; ADelimiter: Char): TStringList;
var
  sList       : TStringList;
  curPos      : Integer;
  subString   : String;
  { DelimiterPos : Integer}
begin
  curPos := 1;
  sList := TStringList.Create;
  while (curPos <= Length(AString)) do 
  begin
    subString := '';
    While (AString[curPos] <> ADelimiter) and
          (curPos <= Length(AString)) do 
    begin
      subString := subString + Copy(AString,curPos,1);
      curPos := curPos + 1;
    end;
    sList.Add(subString);
    curPos := curPos + 1;
  end;
  Result := sList;
end;

The file consist of around 2000 lines. one line looks like this

300: rani : joseph: 210: 500 : 700

If the line has the number 210 at 3rd position,I have to retrieve more details of the employee which is stored in database. How I can do it?

I want to read all the lines in the file.

Thanks for your time.

Arioch 'The
  • 15,799
  • 35
  • 62
user1469630
  • 191
  • 3
  • 5
  • 15
  • Please show us the complete program. We've no idea what `tsl` is. Or `substrings`. I cannot imagine why you want to save the file every single time around the loop. – David Heffernan Feb 01 '13 at 15:20
  • Except that, please include also a sample of your input file (`EMP.txt`) and show, how the output file (`FSTRING.txt`) is expected to look like. – TLama Feb 01 '13 at 15:36
  • the Emp.txt file has 2000 lines. One line looks like 300: rani: joseph: 210: 500: 700 If the line has 210 at 3rd position I have to retrieve more details of the employee which is stored in database. i dont know which is the best way to acheive it. If Im using an output file, i want to store only the 300 and Rani – user1469630 Feb 01 '13 at 15:39
  • @user You're leaking one TStringList instance per line in your file, and your indentation was really bad which made your code very hard to read. – jachguate Feb 01 '13 at 15:47
  • The code in `SubStrings` is an owful re-implementation of `TStrings.DelimitedText`; I don't understand what you'd like in the file. Since your `substrings` function creates a new `TStringList` instance *every time*, you'll only have the data from one line in emp.txt; What exactly would you like the "fstring.txt" file to contain? – Cosmin Prund Feb 01 '13 at 15:50
  • and so - do u need every of 2000 or only 1st one of 2000 ? take 1st few lines, copy them to http://pastebin.ca and give the link. /// Actually - how to split string was discussed very very often... In my answer i gave u one of the dozens links you can get just by searching *delphi split string* here – Arioch 'The Feb 01 '13 at 15:54
  • I want to read all line the file. – user1469630 Feb 01 '13 at 16:13
  • then do standard Pascal loop about it. However do think how you would put the results - u make one file which would be deleted and overwritten on every new line -0 change it how u think u need. See my answer as a skeleton for the code you would make. – Arioch 'The Feb 01 '13 at 16:14
  • Also please, register on StackOverflow and participate in the community life. At least vote for answers and do accept those that helped you to solve your problem. Additionally, you seem to extend and extend your question further and further. There is a thin line between putting more details about problem and substituting problem with another one. To be polite here you make one question for problem, and then accept the answer that helped you and then make another question for another problem. It is really thin line, but i feel, personally, that your question now is more vast than it was. – Arioch 'The Feb 01 '13 at 16:29
  • @user1469630 : Could you somehow get ahead with your problem? Could my answer help you? – moskito-x May 10 '13 at 16:00

2 Answers2

1

Don't forget to reclaim the memory from tsl so it won't leak.

It seems you're came from some garbage-collected language, lazy oen where u do not think about memory at all, like PHP or Python.

So you'd better read Delphi help about objects and their life, or read some book liek Delphi Foundations.

Until that... Variant 3: Since you seems not having the required skill to control and manage lifetime of objects, then use reference-counted types, like arrays or interfaces, for which Delphi controls their lifetime more or less.

Elaborating from the answers from Split a string into an array of strings based on a delimiter you can draft few variants, for example:

var sda: TStringDynArray; 
begin
  sda := SplitString(LineOfText, ':' );
  Assignfile ( filehan2, 'FSTRING.txt');
  Rewrite ( filehand2 );
  try
    WriteLN (filehan2, sda[0]);   WriteLN (filehan2, sda[1]);
  finally
    CloseFile(filehan2);
  end;
end;

Okay - since you told you have old Delphi 7 - you do not have SplitString function there. But you can spare few minutes and make one. http://pastebin.ca/2309695

You also can get helpful Jedi CodeLib library from http://jcl.sf.net

var isl1, isl2: IJclStringList;
begin
  isl1 := TJclStringList.Create;
     isl1.LoadFromFile('EMP.txt');
  isl2 := TJclStringList.Create.Split(isl1[0], ':');
  isl1.Clear.Add( [ isl2[0], isl2[1] ] ).SaveToFile('FSTRING.txt');
end;   

With the sample like 300: rani : joseph: 210: 500 : 700 it seems you have a lot of spaces around real data. Then you should trim those spaces off. Like WriteLN (filehan2, Trim( sda[0] )); or like isl1.Clear.Add( [ Trim( isl2[0] ),..... Read manuals about Trim function;


If the line has the number 210

Then check it, just with "if" statement;

var isl1, isl2, isl3: IJclStringList; 
    EveryLine: string; i: integer;
begin
  isl1 := TJclStringList.Create;
  isl2 := TJclStringList.Create;
  isl3 := TJclStringList.Create;

  isl1.LoadFromFile('EMP.txt');

// for EveryLine in isl1 do begin 
//    - this works in free Lazarus or modern Delphi, but not in D7 }
  for i := 0 to isl1.Count - 1 do begin;
      EveryString := isl1[i];

      isl2.Split(EveryString, ':').Trim;
      if isl2.Count >= 4 then // does 3rd element even exist ???
         if StrToIntDef( isl2[3], -1 ) = 210 then
            CallSomeProcedureToRetrieveMoreDetails; 
      isl3.Clear.Add( [ isl2[0], isl2[1] ] ).SaveToFile('FSTRING.txt');
  end; // for
end;  // function
Community
  • 1
  • 1
Arioch 'The
  • 15,799
  • 35
  • 62
  • In your loop `FSTRING.txt` file will always overwritten. With `isl3.Clear.Add( [ isl2[0], isl2[1] ] ).SaveToFile('FSTRING.txt');` there will be only the last line from EMP.txt in the file FSTRING.txt. – moskito-x Feb 02 '13 at 18:01
  • @moskito-x exactly. but perhaps u'd follow the very story. In the beginning the author told he only need 1st line and does nnot need the rest. Then he told he needs the rest too. It is rather hard to understand what he wants. So all i can o is to base my code on his code. And his code does exactly this - rewrites a file and saves one line there. In may comments i already told about the file being regularly deleted - but it is topicstarter to deside what to do with the data, after it was extracteed for him. I cannot guess what he mades inside his app. – Arioch 'The Feb 02 '13 at 22:38
  • Overwrite a file in a loop again and again so that in the end only 1 row is left in the file, is incorrect. One should not use the same error in its own code. – moskito-x Feb 02 '13 at 23:22
  • however i should also not make fantasies and do what i want instead of what does topic starter want. I pointed him at the problem but it is his choice what he really wants to do. His file operation was a stub, and i kept the stub. He would replace the stub with actual code. – Arioch 'The Feb 03 '13 at 15:54
0

I know there are more elegant variations but these should be simple and understandable.

try your variables is not not to be confused

  Assignfile ( filehan, 'EMP.txt');
  Reset ( filehand );
  CloseFile (FFile);

One filehan and the other filehand and FFile

The particular characteristics of a TStringList, your SubStrings function needs only one line of code.

sList.text:=StringReplace(AString,ADelimiter,#13#10,[rfReplaceAll]);
  • only 4 variables.
  • only 1 TStringList .

Tested with Delphi 5

var
  LineOfText   : String;
  sList : TStringList;
  filehand,Outfilehand: text;

function SubStrings(AString: String; ADelimiter: Char; var sList: TStringList):Boolean;
begin
  sList.text:=StringReplace(AString,ADelimiter,#13#10,[rfReplaceAll]);
end;

begin
  sList := TStringList.Create;
  Assignfile ( filehand, 'EMP.txt');
  Assignfile ( Outfilehand, 'FSTRING.txt');
  Reset ( filehand );
  Rewrite(Outfilehand);
  try
  While not EOF(filehand) do
  begin
    ReadLn  ( filehand, LineOfText );
    LineOfText:=StringReplace(LineOfText,': ',':',[rfReplaceAll]);
    LineOfText:=StringReplace(LineOfText,' :',':',[rfReplaceAll]);
    if pos(':210:',LineOfText)>0 then begin
       substrings(LineOfText, ':' ,sList);
        if (sList.Count=6) then
           if (sList[3]='210') then writeln(Outfilehand,sList[0]+';'+sList[1]);
    end;
  end;
  finally
  sList.Free;
  CloseFile (filehand);
  CloseFile (Outfilehand);
  end;

UPDATE:

I understood the question so that you are only in the row with 210 field value are interested. If you want all the lines in the new file, replace .

if pos(':210:',LineOfText)>0 then begin
        substrings(LineOfText, ':' ,sList);
            if (sList.Count=6) then
               if (sList[3]='210') then writeln(Outfilehand,sList[0]+';'+sList[1]);
end;

with

substrings(LineOfText, ':' ,sList);
   if (sList.Count=6) then
         if (sList[3]='210') then 
         writeln(Outfilehand,sList[0]+';'+sList[1]+';'+sList[4]+';'+sList[5]);
   if (sList.Count=3) then
         writeln(Outfilehand,sList[0]+';'+sList[1]);

Based on the size or value of sList[3] :

  • You can self define which fields are written to FSTRING.txt.

UPDATE2:

How I would do it.

var
  ParsedText   : String;
  inList,outList,sList : TStringList;
  i:integer;

function SubStrings(lineText: String; var sList: TStringList):String;
begin
  result:='ERROR';
  lineText:=StringReplace(lineText,': ',':',[rfReplaceAll]);
  lineText:=StringReplace(lineText,' :',':',[rfReplaceAll]);
  sList.text:=StringReplace(lineText,':',#13#10,[rfReplaceAll]);
    if (sList.Count=6)    then
      if (sList[3]='210') then result:=sList[0]+';'+sList[1]+';'+sList[4]+';'+sList[5] else
                               result:=sList[0]+';'+sList[1];
    if (sList.Count=3)    then result:=sList[0]+';'+sList[1];
end;

begin
  inList  := TStringList.Create;
  outList := TStringList.Create;
  sList   := TStringList.Create;
  try
  inList.LoadFromFile('EMP.txt');
    for i:= 0 to inList.Count-1 do begin
     ParsedText := SubStrings(inList[i],sList);
     if ParsedText <> 'ERROR' then outList.Add(ParsedText);
    end;
  outList.SaveToFile('FSTRING.txt');
  finally
  inList.Free;
  outList.Free;
  sList.Free;
  end;
end;
moskito-x
  • 11,832
  • 5
  • 47
  • 60
  • `function SubStrings(AString: String; ADelimiter: Char; var sList: TStringList):Boo` why is it function if you do not return no result value ? – Arioch 'The Feb 02 '13 at 22:41
  • `if pos(':210:',LineOfText)>0 then begin` i read his question that he wishes to save 0th and 1st columns for EVERY line and plus to that to have extra processing for 210-marked lines. Also i wonder what would u do with `': 0210 :'` :-) – Arioch 'The Feb 02 '13 at 22:42
  • 1.) I have understood the OP is only interested: `lines with 210 at 4th position`. If not so, you can leave out the test `if = :210:` ! 2.) I let the `substring` as a function to test for `LineOfText` is permissible or not. If not then "false" as return. – moskito-x Feb 02 '13 at 23:15
  • 2) u missed the point. You function would return false negative on strings containing like ":0210:". You may argue that storing numbers with leading zeroes is not usual thing, but your function is still at err there. – Arioch 'The Feb 03 '13 at 15:57