CsvHelper
CsvHelper copied to clipboard
Empty DataTable when setting HasHeaderRecord = false
Hi
I'm trying to read the csv, but as soon as I set HasHeaderRecord = false
, then I get an empty table.
version:12.1.2
1,one,yes,a
2,two,no,b
using (var reader = new StreamReader("d:\\text.txt"))
using (var csv = new CsvReader(reader, new Configuration{ Delimiter=",", Encoding = Encoding.UTF8, HasHeaderRecord = false}))
{
using (var dr = new CsvDataReader(csv))
{
var dt = new DataTable();
dt.Load(dr);
//the table is empty
}
}
Same issue here. Any ideas @dmitriy-shleht ?
Looks like currently there is no way to create IDataReader based on csv without header and read first row:
public CsvDataReader(CsvReader csv)
{
this.csv = csv;
csv.Read();
if (csv.Configuration.HasHeaderRecord)
{
csv.ReadHeader();
}
else
{
skipNextRead = true;
}
}
I'll add this as a feature.
In fact, it doesn't return any rows at all.
https://github.com/JoshClose/CsvHelper/blob/89edc486b51086453bc91e043f0f82789374b829/src/CsvHelper.Tests/DataTableTests/CsvDataReaderTests.cs#L133
I think the key here is that CsvDataReader.GetSchemaTable() doesn't add any rows if csv.Configuration.HasHeaderRecord is false.
I am getting the same issue - the table is empty when HasHeaderRecord = false
do you know when a fix for this will be released?
thanks
Also unable to use this lib because of this error. Will have to switch libs if not resolved soon, which is a shame because I really like this one.
Fix incoming?
Also, returning an empty dataset when a reasonable configuration option is set to false is adequately unexpected behavior that this should definitely be considered a bug. This really isn't a feature request no matter how you spin it. This is a bug and marking it as a feature request deprioritizes work on it unnecessarily.
For interim, I wrote the following to use the CsvHelper without a header row to return a DataTable. It does create columns with just the index as the name. Open to better solutions until a fix is implemented.
var data = new DataTable();
bool createColumns = true;
using (var reader = new StreamReader(filename))
using (var csv = new CsvReader(reader))
while (csv.Read())
{
if (createColumns)
{
for (int i = 0; i < csv.Context.Record.Length; i++)
data.Columns.Add(i.ToString());
createColumns = false;
}
DataRow row = data.NewRow();
for (int i = 0; i < csv.Context.Record.Length; i++)
row[i] = csv.Context.Record[i];
data.Rows.Add(row);
}
return data;
Have we got any solution for this??
I'll add this as a feature.
Any update on this?
18 months later, still an issue.
Any update on this?
For interim, I wrote the following to use the CsvHelper without a header row to return a DataTable. It does create columns with just the index as the name. Open to better solutions until a fix is implemented.
Thank you! I almost gave up switching to a different library when I found your useful comment.
https://www.joelverhagen.com/blog/2020/12/fastest-net-csv-parsers gives a nice overview about many CSV parsers and their performance, but not functional capability.
[..]
for (int i = 0; i < csv.Context.Record.Length; i++)
But I had to add "Parser." at 3 places, e.g.: for (int i = 0; i < csv.Context.Parser.Record.Length; i++)
I am just trying to do this: var config = new CsvConfiguration(CultureInfo.InvariantCulture) { HasHeaderRecord = false };
var reader = new StreamReader(filestream);
var csv = new CsvReader(reader, config);
return csv;
Doesn't return anything if the header record is false. This is a showstopper for me, I want to read all the records so the user can tell me which row the header record is on.
I have the same problem. Any fix comming?
I have the same problem. It's a showstopper as well. Any fix? Perhaps a reasonable work around?
I can see the PR for this work is still in peer review state. Is there any news on when this may be reviewed @JoshClose ?
Hi. I did the following:
public CsvDataReader(CsvReader csv)
{
this.csv = csv;
readCountRows = csv.Configuration.ReadCountRows;
csv.Read();
if (csv.Configuration.HasHeaderRecord)
{
csv.ReadHeader();
}
else
{
csv.Configuration.HasHeaderRecord = true;
csv.GenerateHeader();
skipNextRead = true;
}
}
public void GenerateHeader()
{
context.HeaderRecord = new string[context.Record.Length];
for (int i = 0; i < context.HeaderRecord.Length; i++)
{
context.HeaderRecord[i] = $"Column{i+1}";
}
ParseNamedIndexes();
}
Fixed.