It seems interesting. I'vre archived it, and will have a look when there is available time or mood...
Thx and Well done.. --- Óôéò Ôñßô., 19/05/09, ï/ç Theodoros Bebekis <[email protected]> Ýãñáøå: Áðü: Theodoros Bebekis <[email protected]> ÈÝìá: Re: [delphi-en] CVS Parser? Ðñïò: [email protected], [email protected], [email protected] Çìåñïìçíßá: Ôñßôç, 19 ÌÜéïò 2009, 15:07 > From: [email protected] <mailto:delphi-en%40yahoogroups.com> > [mailto:[email protected] <mailto:delphi-en%40yahoogroups.com>] > On Behalf > Of Theodoros Bebekis > Sent: Monday, May 18, 2009 10:41 AM > To: [email protected] <mailto:delphi-en%40yahoogroups.com> > Subject: [delphi-en] CVS Parser? > > Hi > > Is there any freeware CVS parser out there for Delphi 6-7? > One that can handle fields containing line breaks (CRLF), double quotes, and > commas > according to the CVS spec (http://tools.ietf.org/html/rfc4180 > <http://tools.ietf.org/html/rfc4180>)? > > -- > Regards > Theo I finally wrote a csv parser. I took the parsing code from TStrings.SetDelimitedText() private method. In case anyone has a need of such a code, here is the unit. Use it at your own risk. //============================================================= unit o_CSVParser; interface uses Windows ,SysUtils ,Classes ,Controls ,Contnrs ,Types ,DB ; type (*---------------------------------------------------------------------------- Represents a line in the source file. Used internally by the parser ----------------------------------------------------------------------------*) TLine = class(TObject) private Fields : TStringDynArray; public constructor Create(FieldCount: Integer); end; (*---------------------------------------------------------------------------- Parses .csv files Provides two Parse() methods. 1. The first Parse() version parses data and creates an internal list of TLine objects. After successful parsing (LineCount > 0) access parsed data using the function GetValue(const LineIndex, FieldIndex: Integer): string; 2. The second Parse() version parses data into an already created and Active TDataset. Example: Table := TClientDataSet.Create(Self); Table.FieldDefs.Add('CODE' , ftString, 32); Table.FieldDefs.Add('DATE' , ftString, 24); Table.FieldDefs.Add('AMOUNT' , ftString, 16); Table.FieldDefs.Add('DEBIT_CREDIT' , ftString, 8); Table.FieldDefs.Add('CURRENCY_CODE' , ftString, 8); Table.FieldDefs.Add('VAT_CODE' , ftString, 8); Table.CreateDataSet(); Table.Active := True; ParseCSV('FileName.csv', Table, True, ';'); ----------------------------------------------------------------------------*) TCSVParser = class(TObject) private FList : TObjectList; FFieldCount : Integer; FDelimiter : AnsiChar; FMS : TMemoryStream; FFieldIndex : Integer; FInFirstLine : Boolean; FSkipFirstLine : Boolean; FCurrentLine : TLine; FToDataset : Boolean; FTable : TDataset; procedure ExtractValues(P: PChar); procedure AddFieldValue(const S: string); function get_LineCount: Integer; procedure DoParse(const FileName: string; FieldCount: Integer; SkipFirstLine: Boolean; Delimiter: AnsiChar); public constructor Create; destructor Destroy; override; procedure Clear; procedure Parse(const FileName: string; FieldCount: Integer; SkipFirstLine: Boolean; Delimiter: AnsiChar = ';' ); overload; procedure Parse(const FileName: string; Table: TDataset; SkipFirstLine: Boolean; Delimiter: AnsiChar = ';'); overload; function GetValue(const LineIndex, FieldIndex: Integer): string; property LineCount : Integer read get_LineCount; end; procedure ParseCSV(const FileName: string; Table: TDataset; SkipFirstLine: Boolean; Delimiter: AnsiChar = ';'); implementation (*---------------------------------------------------------------------------- Parses FileName source file into Table TDataset. The Table must be already created and Active. Set SkipFirstLine to True when the first line in the source file contains field names Delimiter is the field delimiter character ----------------------------------------------------------------------------*) procedure ParseCSV(const FileName: string; Table: TDataset; SkipFirstLine: Boolean; Delimiter: AnsiChar); var Parser: TCSVParser; begin Parser := TCSVParser.Create; try Parser.Parse(FileName, Table, SkipFirstLine, Delimiter); finally Parser.Free; end; end; { TLine } (*----------------------------------------------------------------------------*) constructor TLine.Create(FieldCount: Integer); begin inherited Create; SetLength(Fields, FieldCount); end; { TCSVParser } (*----------------------------------------------------------------------------*) constructor TCSVParser.Create; begin inherited Create; FList := TObjectList.Create(True); end; (*----------------------------------------------------------------------------*) destructor TCSVParser.Destroy; begin FList.Free; inherited; end; (*----------------------------------------------------------------------------*) procedure TCSVParser.Clear; begin FList.Clear; FFieldCount := 0; FDelimiter := ';'; FFieldIndex := 0; FInFirstLine := True; end; (*----------------------------------------------------------------------------*) function TCSVParser.get_LineCount: Integer; begin Result := FList.Count end; (*----------------------------------------------------------------------------*) function TCSVParser.GetValue(const LineIndex, FieldIndex: Integer): string; begin Result := TLine(FList[LineIndex]).Fields[FieldIndex]; end; (*----------------------------------------------------------------------------*) procedure TCSVParser.AddFieldValue(const S: string); begin if FSkipFirstLine and FInFirstLine then begin Inc(FFieldIndex); if FFieldIndex > FFieldCount - 1 then begin FInFirstLine := False; FFieldIndex := 0; end; end else if FToDataset then begin if FFieldIndex = 0 then begin FTable.Append; FTable.Edit(); end; FTable.Fields[FFieldIndex].Value := S; Inc(FFieldIndex); if FFieldIndex > FFieldCount - 1 then begin FTable.Post(); FFieldIndex := 0; end; end else begin if FFieldIndex = 0 then FCurrentLine := TLine.Create(FFieldCount); FCurrentLine.Fields[FFieldIndex] := S; Inc(FFieldIndex); if FFieldIndex > FFieldCount - 1 then begin FList.Add(FCurrentLine); FFieldIndex := 0; end; end; end; (*---------------------------------------------------------------------------- parsing code is stolen from TStrings.SetDelimitedText() private method ----------------------------------------------------------------------------*) procedure TCSVParser.ExtractValues(P: PChar); var P1: PChar; S: string; begin while P^ in [#1..' '] do P := CharNext(P); while P^ <> #0 do begin if P^ = '"' then S := AnsiExtractQuotedStr(P, '"') else begin P1 := P; while (P^ > ' ') and (P^ <> FDelimiter) do P := CharNext(P); SetString(S, P1, P - P1); end; AddFieldValue(S); // <==== while P^ in [#1..' '] do Inc(P); if P^ = FDelimiter then begin P1 := P; if CharNext(P1)^ = #0 then AddFieldValue(''); // <==== repeat P := CharNext(P); until not (P^ in [#1..' ']); end; end; end; (*----------------------------------------------------------------------------*) procedure TCSVParser.DoParse(const FileName: string; FieldCount: Integer; SkipFirstLine: Boolean; Delimiter: AnsiChar); var NUL : Char; begin FFieldCount := FieldCount; FDelimiter := Delimiter; FSkipFirstLine := SkipFirstLine; if FileExists(FileName) then begin FMS := TMemoryStream.Create; try FMS.LoadFromFile(FileName); FMS.Position := 0; if FMS.Size > 0 then begin FMS.Position := FMS.Position + FMS.Size; NUL := #0; FMS.WriteBuffer(NUL, 1); FMS.Position := 0; ExtractValues(FMS.Memory); end; finally FMS.Free; end; end; end; (*---------------------------------------------------------------------------- Parses FileName source file. FieldCount is the number of fields in the FileName source file Set SkipFirstLine to True when the first line in the source file contains field names Delimiter is the field delimiter character After successful parsing (LineCount > 0) access parsed data using the function GetValue(const LineIndex, FieldIndex: Integer): string; ----------------------------------------------------------------------------*) procedure TCSVParser.Parse(const FileName: string; FieldCount: Integer; SkipFirstLine: Boolean; Delimiter: AnsiChar); begin Clear(); FToDataset := False; DoParse(FileName, FieldCount, SkipFirstLine, Delimiter); end; (*---------------------------------------------------------------------------- Parses FileName source file into Table TDataset. The Table must be already created and Active. Set SkipFirstLine to True when the first line in the source file contains field names Delimiter is the field delimiter character ----------------------------------------------------------------------------*) procedure TCSVParser.Parse(const FileName: string; Table: TDataset; SkipFirstLine: Boolean; Delimiter: AnsiChar); begin Clear(); FToDataset := True; FTable := Table; DoParse(FileName, Table.FieldCount, SkipFirstLine, Delimiter); end; end. -- Regards Theo ------------------------ Theo Bebekis Thessaloniki, Greece ------------------------ C# and Delphi tutorials at http://teo.bebekis.googlepages.com/ ------------------------ Greek_Delphi_Prog : a greek Delphi list at http://groups.yahoo.com/group/Greek_Delphi_Prog CSharpDotNetGreek : a greek C# and .Net list at http://groups.yahoo.com/group/CSharpDotNetGreek atla_custom : an ALTEC Atlantis Customization list at http://groups.yahoo.com/group/atla_custom ------------------------ ------------------------------------ ----------------------------------------------------- Home page: http://groups.yahoo.com/group/delphi-en/ To unsubscribe: [email protected]! Groups Links ___________________________________________________________ ×ñçóéìïðïéåßôå Yahoo!; ÂáñåèÞêáôå ôá åíï÷ëçôéêÜ ìçíýìáôá (spam); Ôï Yahoo! Mail äéáèÝôåé ôçí êáëýôåñç äõíáôÞ ðñïóôáóßá êáôÜ ôùí åíï÷ëçôéêþí ìçíõìÜôùí http://login.yahoo.com/config/mail?.intl=gr [Non-text portions of this message have been removed] ------------------------------------ ----------------------------------------------------- Home page: http://groups.yahoo.com/group/delphi-en/ To unsubscribe: [email protected]! Groups Links <*> To visit your group on the web, go to: http://groups.yahoo.com/group/delphi-en/ <*> Your email settings: Individual Email | Traditional <*> To change settings online go to: http://groups.yahoo.com/group/delphi-en/join (Yahoo! ID required) <*> To change settings via email: mailto:[email protected] mailto:[email protected] <*> To unsubscribe from this group, send an email to: [email protected] <*> Your use of Yahoo! Groups is subject to: http://docs.yahoo.com/info/terms/

