Parsing a csv file

delphi United States
  • 15 years ago

    Hi,
    Help - I'm stuck!!  I'm trying to copy a list of countries from a csv file to text file and I'm trying to get to the position of each country on each line?
    Thanks ,
    Junior

  • 15 years ago

    Quote:
    [1]Posted by et33 on 20 Nov 2005 11:18 AM[/1]
    Hi,
    Help - I'm stuck!!  I'm trying to copy a list of countries from a csv file to text file and I'm trying to get to the position of each country on each line?
    Thanks ,
    Junior


    Hi,


    Your question sounds very confusing. I assume that you have two questions here.


    1.  How to copy a list of countries from a csv file to text file?
       All you need to do is to write a copy file function to copy a csv file to a text file:


      procedure FileCopy(const FileFrom, FileTo: string) ;
      var FromF, ToF: file;
            NumRead, NumWritten: Word;
            Buffer: array[1..2048] of Byte;
      begin
        AssignFile(FromF, FileFrom) ;
        Reset(FromF, 1) ;
        AssignFile(ToF, FileTo) ;
        Rewrite(ToF, 1) ;
        repeat
        BlockRead(FromF, Buffer, SizeOf(Buffer), NumRead) ;
        BlockWrite(ToF, Buffer, NumRead, NumWritten) ;
        until (NumRead = 0) or (NumWritten <> NumRead) ;
        CloseFile(FromF) ;
        CloseFile(ToF) ;
      end;


    2.  How to get the position of each country on each line?
        Assumption  Each country is being found on different lines as shown below:
        Africa
        Australia
        Austria
        China
        Japan
        Malaysia
        Phillippines
       
        and the file content is loaded into a TStringList to be read to show the user each line of the country with a sequence number by it's side.



        procedure GetCountry(CountryFilePath: string);
        var CountryLst : TStringList;
              i : integer;
        begin
          //Check to ensure that the file exists
          if not FileExists(CountryFilePath) then begin
            beep;
            ShowMessage('Country file: ' + CountryFilePath + ' does not exist.');
            exit;
          end;


          //Loads contents into CountryLst
          try
            CountryLst := TStringList.Create;
            CountryLst.Clear;
            CountryLst.LoadFromFile(CountryFilePath);


            for i := 0 to CountryLst.Count - 1 do
              ShowMessage(IntToStr(i + 1) + ': ' + CountryLst.Strings); //Shows: 1: Africa and lets the user to click on the OK button before continuing


          finally
            CountryLst.Free;
          end;
        end;


    Hope this helps.

  • 15 years ago

    Use the following routine to add the records into a string list :


    Code:

    //
    // RecordBuff = File contents
    // Delimeter   = Character user to seperate record, eg ','
    // Fields         = The stringlist to be filled with the record values
    //
    Function ExtractFields(RecordBuff : String; Delimeter : Char; Fields : TStrings) : Integer;
    Var
      Buffer  : PChar;
      counter : Longint;
      oCount  : Longint;
      bLen    : Longint;
      inQuotes : Boolean;
      lastQuote : Char;
      str       : String;


      Procedure AddChar(Const Ch : Char);
       begin
         If (Length(str) < SizeOf(Str)) then str := str + Ch
          else
          begin
            Fields.Add(str);
            FillChar(str, SizeOf(Str), #0);
            str := Ch;
         end;
      end;


    begin
      oCount := Fields.Count;
      str := RecordBuff;
      If (Pos(Delimeter, str) > 0) then
       begin
         Buffer := RecordBuff;
         str := '';
         InQuotes := False;
         lastQuote := #0;
         bLen := StrLen(Buffer);


         { We go to the end of the buffer, incase the last item }
         { does not have the "Delimeter" character              }


         For counter := 0 to bLen do
          begin
            Case Buffer[counter] of
              #00 : begin
                      If not InQuotes then
                       begin
                         If (Buffer[Counter - 1] <> Delimeter) then
                          Fields.Add(str);
                         Break;  { It's the end ! }
                       end
                       else AddChar(#0);
              end;
              #34 : begin
                      If inQuotes then
                       begin
                         If (lastQuote = #34) then inQuotes := False;
                       end
                       else inQuotes := True;
                      AddChar(#34);
              end;
              #39 : begin
                      If inQuotes then
                       begin
                         If (lastQuote = #39) then inQuotes := False;
                       end
                       else inQuotes := True;
                      AddChar(#39);
              end;


             else
               If (Buffer[counter] = Delimeter) then
                 begin
                   If not inQuotes then
                     begin
                       Fields.Add(str);
                       str := '';
                     end
                     else AddChar(Delimeter);
                 end
                 else AddChar(Buffer[counter]);
            end;
         end;
       end
       else Fields.Add(str);
      Result := Fields.Count - oCount;
    end;




    For instance :


    Code:


    Procedure Form1.LoadFile;
    Var
        l : TStringList;
        s : String;
        i  : Integer;
    begin
       l := TStringList.Create;
       Try
          l.LoadFromFile(FileName);
          s := l.Text;
          l.Clear;
          ExtractFields(s, ',',  l)
         
         l.SaveToFile(AnotherFileName);


         For i := 0 to Pred(l.Count) do
          begin  
              // Do whatever you need here
         end;


         finally
           l.Free;
       end;
    end;



  • 15 years ago

    Hi Vivienne,


    Thank-you for your reply, sorry I didn't explain myself clearly!  I have got to the stage of reading in each line into a separate string in a stringlist, however, the Country is the 8th position in the string, so it has text before and after it.  For example:
    "ALFKI","Alfreds Futterkiste","Maria Anders","Sales Representative","Obere Str. ,"Berlin",,"12209","Germany","030-0074321","030-0076545"
    I'm not sure on the easiest way to extract the 8th string only, any ideas?
    Thanks again,
    Ellen.

  • 15 years ago

    Dave,
    Thanks for your reply.

  • 15 years ago

    Quote:
    [1]Posted by et33 on 4 Dec 2005 08:40 PM[/1]
    Hi Vivienne,


    Thank-you for your reply, sorry I didn't explain myself clearly!  I have got to the stage of reading in each line into a separate string in a stringlist, however, the Country is the 8th position in the string, so it has text before and after it.  For example:
    "ALFKI","Alfreds Futterkiste","Maria Anders","Sales Representative","Obere Str. ,"Berlin",,"12209","Germany","030-0074321","030-0076545"
    I'm not sure on the easiest way to extract the 8th string only, any ideas?
    Thanks again,
    Ellen.




    Hi Ellen,


    I don't have any easiest way to do such extraction but I can share with you what I do with such situation and show the country in the listbox.


    I take each line of the csv file contain data in the format that you have shown above: "ALFKI","Alfreds Futterkiste","Maria Anders","Sales Representative","Obere Str. ","Berlin","12209","Germany","030-0074321","030-0076545"


    procedure ReadCountryIntoListBox(DataFile : String);
    var DataLst : TStringList;
         i, j : integer;
         TempStr : string;
    begin
      if not FileExists(DataFile) then begin
         beep;
         ShowMessage('Data file: ' + DataFile + ' does not exist.');
         exit;
      end;


      //Loads contents into DataLst
      try
         DataLst := TStringList.Create;
         DataLst.Clear;
         DataLst.LoadFromFile(DataFile);
         CountryLst.clear; //clears the ListBox


         for i := 0 to DataLst.Count - 1 do begin
           TempStr := DataLst.strings;
           for j := 1 to 8 do begin
              if (j < 8) then
                 TempStr := Copy(TempStr, pos(',', TempStr) + 1, Length(tempStr) - pos(',', tempstr))
              else begin
                 CountryLst.Add(Copy(TempStr, 1, pos(',', TempStr) - 1));
                 break;
              end;
           end;
         end;


      finally
         CountryLst.Free;
      end;


    end;


    I hope this can help you.




  • 15 years ago
    Thanks for your response, that did cross my mind but i think i was trying to make things too complicated for myself!

Post a reply

Enter your message below

Sign in or Join us (it's free).

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“Programs must be written for people to read, and only incidentally for machines to execute.”