Home > Blockchain >  CSVHelper, go back to the beginning after reading the header row
CSVHelper, go back to the beginning after reading the header row

Time:09-14

I have the following code where I look at columns headers before some condition statement:

var csvConfig = new CsvHelper.Configuration.CsvConfiguration(CultureInfo.InvariantCulture)
                {
                    // csvconfig.Delimiter = "\t";
                    HasHeaderRecord = true
                };    

using (StreamReader reader = new StreamReader(filePath, Encoding.UTF8))
using (CsvReader csv1 = new CsvReader(reader, csvConfig))
{ 
    
                        CsvReader csv2 = csv1;
                        csv2.Read();
                        csv2.ReadHeader();
    
                        string[] headers = csv2.HeaderRecord;
    if(headers[0].Replace("\0", "").ToUpper() == "TEST")
    {
              using (var dr1 = new CsvDataReader(csv1))
              {
                  var dt1 = new DataTable();
                  dt1.Load(dr1);
              }
    }
}

I thought that by having 2 variables for the CsvReader (csv1 and csv2) it would be feasible but it seems that they both use the same object in memory. Therefore when I want to use csv2 to fill my datatable, the header row has been already read in csv1 and is not loaded in my datatable.

How can I make sure that csv2 contains the whole csv and is distinct from csv1? Is there a method to go back to the beginning or do I need to read the whole CSV again using CsvReader?

Thank you

CodePudding user response:

In C#, datas types are categorized based on how they store their value in the memory : by value or by reference (by pointer exists too).

For example, a string is usually stored by value but complex objects like your reader are almost always stored by reference.

When you do csv2 = csv1 both now refer to the same memory area. This means that they are 2 names for the same thing. When you do an action on csv1, csv2 also receives it since they are 2 aliases for the same information.

Try if CSVreader implements Clone() :

 CsvReader csv2 = csv1.Clone();

If it is, the function will create a new object with the same informations which do not share the same memory area.

CodePudding user response:

You need a separate CsvReader for csv1 and csv2. As both you @UserNam3 advise, you don't want csv2 to be referencing the same object as csv1 in memory. They will both be using the same Stream, so after reading the header with csv2 you will need to reset the Stream back to the beginning.

using (StreamReader reader = new StreamReader(filePath, Encoding.UTF8))
using (CsvReader csv1 = new CsvReader(reader, csvConfig))
using (CsvReader csv2 = new CsvReader(reader, csvConfig))
{
    csv2.Read();
    csv2.ReadHeader();

    string[] headers = csv2.HeaderRecord;
    
    reader.BaseStream.Position = 0;

    if(headers[0].Replace("\0", "").ToUpper() == "TEST")
    {
        using (var dr1 = new CsvDataReader(csv1))
        {
            var dt1 = new DataTable();
            dt1.Load(dr1);
        }
    }
}
  • Related