admin管理员组

文章数量:1402949

The following C# code used to work with csvReader where variable reader is a StreamReader:

DataTable dataTable = null;
this._csvHeaders = null;

using (reader)
{
    using (CsvReader csv = new CsvReader(reader, CultureInfo.InvariantCulture))
    {
        csv.Configuration.HasHeaderRecord = true;
        csv.Configuration.MissingFieldFound = (field, index, context) => AddMissingFieldParseError(field, context.Row, index);
        csv.Configuration.BadDataFound = (context) => AddBadDataFoundParseError(context.Field, context.Row);

        using (CsvDataReader dataReader = new CsvDataReader(csv))
        {
            // Validate headers
            this._csvHeaders = csv.Context.Reader.HeaderRecord.ToList();
            TrimHeaderNames(ref _csvHeaders);

            string errorMessage = string.Empty;

            if (!ValidateHeaders(_csvHeaders, out errorMessage))
            {
                XOperationError operationError = new XOperationError("Duplicated error found", errorMessage);
                this.ParseErrors.Clear();
                this.ParseErrors.Add(0, new List<XOperationError> { operationError });
                return null;
            }

            dataTable = new DataTable();
            dataTable.Load(dataReader);
        }
    }
}

Now it no longer works as HasHeaderRecord, MissingFieldFound, BadDataFound all became read-only.

I tried to remove the 3 lines and added the following before the new CsvReader() statement:

CsvConfiguration config = new CsvConfiguration(CultureInfo.InvariantCulture)
            {
                HasHeaderRecord = true,
                MissingFieldFound = (field, index, context) => AddMissingFieldParseError(field, context.Row, index),
                BadDataFound = (context) => AddBadDataFoundParseError(context.Field, context.Row)
            };

Now it complains:

  1. MissingFieldFound does not take 3 arguments
  2. BadDataFoundArgs does not contain a definition for row

I'm really confused. Are these just syntax errors?

Any help is appreciated.

The following C# code used to work with csvReader where variable reader is a StreamReader:

DataTable dataTable = null;
this._csvHeaders = null;

using (reader)
{
    using (CsvReader csv = new CsvReader(reader, CultureInfo.InvariantCulture))
    {
        csv.Configuration.HasHeaderRecord = true;
        csv.Configuration.MissingFieldFound = (field, index, context) => AddMissingFieldParseError(field, context.Row, index);
        csv.Configuration.BadDataFound = (context) => AddBadDataFoundParseError(context.Field, context.Row);

        using (CsvDataReader dataReader = new CsvDataReader(csv))
        {
            // Validate headers
            this._csvHeaders = csv.Context.Reader.HeaderRecord.ToList();
            TrimHeaderNames(ref _csvHeaders);

            string errorMessage = string.Empty;

            if (!ValidateHeaders(_csvHeaders, out errorMessage))
            {
                XOperationError operationError = new XOperationError("Duplicated error found", errorMessage);
                this.ParseErrors.Clear();
                this.ParseErrors.Add(0, new List<XOperationError> { operationError });
                return null;
            }

            dataTable = new DataTable();
            dataTable.Load(dataReader);
        }
    }
}

Now it no longer works as HasHeaderRecord, MissingFieldFound, BadDataFound all became read-only.

I tried to remove the 3 lines and added the following before the new CsvReader() statement:

CsvConfiguration config = new CsvConfiguration(CultureInfo.InvariantCulture)
            {
                HasHeaderRecord = true,
                MissingFieldFound = (field, index, context) => AddMissingFieldParseError(field, context.Row, index),
                BadDataFound = (context) => AddBadDataFoundParseError(context.Field, context.Row)
            };

Now it complains:

  1. MissingFieldFound does not take 3 arguments
  2. BadDataFoundArgs does not contain a definition for row

I'm really confused. Are these just syntax errors?

Any help is appreciated.

Share Improve this question edited Mar 21 at 5:39 marc_s 756k184 gold badges1.4k silver badges1.5k bronze badges asked Mar 20 at 23:49 T. J. FanT. J. Fan 777 bronze badges 1
  • github/JoshClose/CsvHelper/blob/… – Hans Passant Commented Mar 20 at 23:57
Add a comment  | 

2 Answers 2

Reset to default 1

The call to csv.Configuration actually returns an IReaderConfiguration which is an interface implemented by the underlying CsvConfiguration class. As far as I can tell this was changed in 20.0.0 to avoid threading issues.

The idea is that the Configuration is immutable once it's been passed to the reader. So if you want to change it, you have to inject it (as you've mentioned):

using (reader){    
    var configuration = new CsvConfiguration(CultureInfo.InvariantCulture);
    // Note the culture is now in the configuration
    // Set up the rest of your configuration here

    using (CsvReader csv = new CsvReader(reader, configuration))    {
        // etc.

MissingFieldFound now takes 1 argument, MissingFieldFoundArgs. BadFoundData takes BadDataFoundArgs. It looks like that last one now has a Field, RawRecord and Context. I think Context.Reader might have the info you're looking for with respect to the row, if the context doesn't. Try this:

MissingFieldFound = (args) => AddMissingFieldParseError(args), // MissingFieldFoundArgs
BadDataFound = (args) => AddBadDataFoundParseError(args) // BadDataFoundArgs

Debug those args and you will be able to see what information you can retrieve from them. But setting them up before the using call is the right thing to do.

(You can see the list of changes in the changelog in case you run into further issues.)

I was able to figure out the parameters finally. Here are the solutions:

CsvConfiguration config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
    HasHeaderRecord = true,
    MissingFieldFound = (args) => AddMissingFieldParseError(args.Context.Reader.HeaderRecord, args.Context.Reader.Parser.Row, args.Index),
    BadDataFound = (args) => AddBadDataFoundParseError(args.Field, args.Context.Reader.Parser.Row)
};

本文标签: