Click here to Skip to main content
Click here to Skip to main content

Tagged as

Delphi CSV File and String Reader Classes

, 9 Jun 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
TnvvCSVFileReader and TnvvCSVStringReader are light weighted and fast classes that resemble unidirectional data set

Introduction

Classes I present here are functionally identical to classes described in the article C# CSV File and String Reader Classes and have the same set of public methods and properties that are explained there in detail. All said in that article is also true in this case. It is recommended to read that article first since I am not going to repeat everything here even though there are some minor differences like variable types, etc but the relation between Delphi and C# specifics is obvious. Below, I will outline the CSV Reader features and will also provide the information related to Delphi code use.

TnvvCSVFileReader and TnvvCSVStringReader are light weighted and fast classes that resemble unidirectional data set. They are very simple to use and have properties that allow handling number of existing variations of CSV and “CSV-like” formats.

Classes are derived from abstract TnvvCSVReader class that does not specify data source and instead works with instance of TTextReader class.

TnvvCSVFileReader and TnvvCSVStringReader accept file and string as data sources respectively. They introduce additional “CSV source” related properties and override the abstract method that returns instance of specific TTextReader descendant:

function CreateDataSourceReader: TTextReader; virtual; abstract;

Classes for other CSV data sources can be created in similar way.

CSV Reader features

  • Supports three kinds of line delimiters: <CR>, <CR><LF> and <LF>, all of which can be present in the same CSV file simultaneously. Consequently, the <LF><CR> pair will result in an empty line. This situation can nonetheless be handled by setting property IgnoreEmptyLines to true.
  • Presence of header in the very first record of file is controlled by boolean property HeaderPresent.
  • Empty lines can be ignored (by default they are not ignored).
  • Number of fields is auto-detected (by default) on the base of the first record or must be set explicitly if auto-detection is off.
  • Field separator by default is comma (0x2C) but virtually any (Unicode) character can be used, for example, TAB, etc.
  • Field quoting allows multi-line field values and presence of quote and field separator characters within the field. By default, it is assumed that field may or may not be enclosed in quotes but reader can be instructed not to use field quoting.
  • Quote character by default is double quotes (0x22) but virtually any (Unicode) character can be used. It is assumed that quote character is also used as an escape character.
  • Unicode range of the character codes is assumed by default but can be limited to ASCII only by setting corresponding property to true.
  • Characters with codes below 0x20 (and above 0x7E in ASCII case) are considered to be “Special characters” and by default must not appear in the file. That requirement does not affect line delimiters and field separator and/or quote character if they are from this range. As an option, the reader can be instructed to simply ignore the special characters.
  • Reader itself does not use buffering. It uses memory just enough to store field names and field values of the current record. If any buffering is happening then standard Delphi classes like TStreamReader and TStringReader are responsible for that.
  • Reader supposedly is fast since it reads each character directly from TTextReader and analyzes character just once, i.e. reader does one-pass parsing. Also, parser uses minimum conditional logic.

Using the code

Use is straightforward. Simply create an instance of corresponding class, specify the source of CSV data, modify some properties if necessary, call Open, and iterate through records calling Next. Within each record iterate through the field values. Call Close when done.

Using TnvvCSVFileReader class

uses Nvv.IO.CSV.Delphi.NvvCSVClasses;

procedure ReadCSVFile(const ACSVFilePath: string);
var
  csvReader: TnvvCSVFileReader;
  i: Integer;
begin
  csvReader := TnvvCSVFileReader.Create;
  try
    csvReader.FileName := ACSVFilePath; // Assign CSV data file path
    // Modify values of other input properties if necessary. For example:
    csvReader.HeaderPresent := True;

    csvReader.Open;

    if (csvReader.HeaderPresent) then
      for i:=0 to csvReader.FieldCount-1 do
        DoSomethingWithFieldName(csvReader.Fields[i].Name);

    while (not csvReader.Eof) do
    begin
      for i:=0 to csvReader.FieldCount-1 do
        DoSomethingWithFieldValue(csvReader.Fields[i].Value);

      csvReader.Next;
    end;

    csvReader.Close;
  finally
    csvReader.Free;
  end;
end;

Using TnvvCSVStringReader class

uses Nvv.IO.CSV.Delphi.NvvCSVClasses;

procedure ReadCSVString(const ACSVString: string);
var
  csvReader: TnvvCSVStringReader;
  i: Integer;
begin
  csvReader := TnvvCSVStringReader.Create;
  try
    csvReader.DataString := ACSVString; // Assign string containing CSV data
    // Modify values of other input properties if necessary. For example:
    csvReader.HeaderPresent := True;

    csvReader.Open;

    if (csvReader.HeaderPresent) then
      for i:=0 to csvReader.FieldCount-1 do
        DoSomethingWithFieldName(csvReader.Fields[i].Name);

    while (not csvReader.Eof) do
    begin
      for i:=0 to csvReader.FieldCount-1 do
        DoSomethingWithFieldValue(csvReader.Fields[i].Value);

      csvReader.Next;
    end;
    csvReader.Close;
  finally
    csvReader.Free;
  end;
end;

Notable difference between Delphi and C# CSV Reader classes

Delphi’s counterpart defines an event in the following way:

property OnFieldCountAutoDetectComplete : TNotifyEvent
{- This event fires from within Open if FieldCount_AutoDetect is true. Use of this event is optional since "auto-detected" FieldCount is available upon completion of Open any way.}

Downloading source code

The following source code, which should work with Delphi 2009 (and later versions), is available for download above:  

  • Unit "Nvv.IO.CSV.Delphi.NvvCSVClasses.pas" containing classes TnvvCSVReader, TnvvCSVFileReader and TnvvCSVStringReader.
  • Code part of main form of VCL Forms Application that tests both TnvvCSVFileReader and TnvvCSVStringReader classes is in "CSVReaderTest_MainForm.pas" file. Detailed instruction on how to quickly create test application is provided at the beginning of the file.

History

Version 1.0 (2014-06-08)

  • First release

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Vladimir Nikitenko
Systems Engineer
United States United States
Extensive experience developing pure software and combined soft-hardware systems using variety of languages and tools in following roles: system architect, team leader, software developer, business analyst and so on.

Comments and Discussions

 
GeneralThanks! Downloaded. Pinmemberedwinzyh25-Jul-14 23:01 
QuestionGreat Job, Save a lot of my Time. PinmemberMember 1094534514-Jul-14 5:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.1411023.1 | Last Updated 9 Jun 2014
Article Copyright 2014 by Vladimir Nikitenko
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid