c# - 使用 csvHelper 处理 csv 文件中的无效条目

标签 c# .net csv csvhelper

我目前正在使用 CSV 帮助程序读取 csv 文件的内容并将其输出到控制台。我已经安装了 csvHelper nuget 包。但是,当我运行代码时,出现以下错误:

CsvHelper.TypeConversion.TypeConverterException: '无法执行转换。 文本: '' 成员(member)类型: TypeConverter: 'CsvHelper.TypeConversion.Int32Converter''

据我了解,这是由于 csv 中的字段人口为空所致。我目前希望能够验证该字段并将其设置为 0。如何使用 CSVhelper 执行此操作。

我读取 csv 的代码是:

class ReaderCsv
    {
        private string _cvsfilepath;

        public ReaderCsv(string csvfilepath)
        {
            this._cvsfilepath = csvfilepath;
        }

        public List <Country>  ReadAllCountries()
        {
            var countries = new List<Country>();
            using (var sr = new StreamReader(_cvsfilepath))
            using (var csv = new CsvReader(sr, System.Globalization.CultureInfo.InvariantCulture))
            {


                csv.Configuration.Delimiter = ",";
                csv.Read();
                csv.ReadHeader();

                while (csv.Read()) 
                {
                    var country= new Country();

                    { 
                        country.CountryName = csv.GetField("CountryName");
                        country.CountryCode = csv.GetField("CountryCode");
                        country.Continent = csv.GetField("CountryCode");
                        country.Population = csv.GetField<int>("Population");


                    }
                    countries.Add(country);

                }
            }return countries;


        }

    }
}

我的映射类是


public class CountryMap  : ClassMap<Country>
    {
        public CountryMap()
        {

            Map(m => m.CountryName);
            Map(m => m.CountryCode);
            Map(m => m.Continent);
            Map(m => m.Population);

        }


    }

最佳答案

CSV Helper 提供了 GetField 方法的重载,您可以将自定义类型转换器传递给该方法。

https://joshclose.github.io/CsvHelper/api/CsvHelper/CsvReader/

因此;不仅适用于 Int32,而且适用于任何类型,这是一个使用自定义泛型类型转换器的实现,如果转换失败,该转换器将返回该类型的默认值。

这并不意味着您必须吞下或忽略异常。此转换器还会为您提供转换错误和违规值,以便您可以处理此无效数据。

我还添加了一个 lineNumber 变量来跟踪无效数据所在的行。

希望对您有所帮助。

public class Defaulter<T> : CsvHelper.TypeConversion.ITypeConverter
{
    Exception conversionError;
    string offendingValue;

    public Exception GetLastError()
    {
        return conversionError;
    }

    public string GetOffendingValue()
    {
        return offendingValue;
    }

    object CsvHelper.TypeConversion.ITypeConverter.ConvertFromString(string text, IReaderRow row, CsvHelper.Configuration.MemberMapData memberMapData)
    {
        conversionError = null;
        offendingValue = null;
        try
        {
            return (T)Convert.ChangeType(text, typeof(T));
        }
        catch (Exception localConversionError)
        {
            conversionError = localConversionError;
        }
        return default(T);
    }

    string CsvHelper.TypeConversion.ITypeConverter.ConvertToString(object value, IWriterRow row, CsvHelper.Configuration.MemberMapData memberMapData)
    {
        return Convert.ToString(value);
    }
}

这里是您的代码的修改版本,用于跟踪行号以及根据需要处理错误:

public class ReaderCsv
{
    private string _cvsfilepath;

    public ReaderCsv(string csvfilepath)
    {
        this._cvsfilepath = csvfilepath;
    }

    public List<Country> ReadAllCountries()
    {
        var countries = new List<Country>();
        using (var sr = new StreamReader(_cvsfilepath))
        using (var csv = new CsvReader(sr, System.Globalization.CultureInfo.InvariantCulture))
        {
            csv.Configuration.Delimiter = ",";
            csv.Read();
            csv.ReadHeader();

            Defaulter<int> customInt32Converter = new Defaulter<int>();

            int lineNumber = 0;

            while (csv.Read())
            {
                lineNumber++;
                var country = new Country();
                {
                    country.CountryName = csv.GetField("CountryName");
                    country.CountryCode = csv.GetField("CountryCode");
                    country.Continent = csv.GetField("CountryCode");
                    country.Population = csv.GetField<int>("Population", customInt32Converter);

                    if (customInt32Converter.GetLastError() != null)
                    {
                        // The last conversion has failed.
                        // Handle it here.
                        string errorMessage = "The conversion of Population field on line " + lineNumber + " has failed. The Population value was: [" + customInt32Converter.GetOffendingValue() + "]";

                    }
                }
                countries.Add(country);

            }
        }
        return countries;
    }
}

问候。

关于c# - 使用 csvHelper 处理 csv 文件中的无效条目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60762144/

相关文章:

c# - 如何使用 Novacode DocX 在表上设置 "keep with next"属性?

c# - DateTime 在当前上下文中不存在

python - 删除一系列 csv 列

c# - IoC 和 .NET 框架

c# - 向 DBContext 添加重载

.net - 使参数化查询同时适用于 SQL Server 和 Oracle

r - data.table::fread 中的 dec 参数

javascript - D3 尝试更改 csv 导入的数据

c# - 绑定(bind)特定附加属性的值

c# - 将 ToolStripSplitButton.DropDown 按钮宽度设置为 0