使用 csvHelper 处理 csv 文件中的无效条目
Handle invlaid entries in csv file with csv Helper
我目前正在使用 CSV 帮助程序读取 csv 文件的内容并将其输出到控制台。我已经安装了 csvHelper nuget 包。但是,当我 运行 代码时,出现以下错误:
CsvHelper.TypeConversion.TypeConverterException: '无法进行转换。
文本: ''
会员类型:
类型转换器:'CsvHelper.TypeConversion.Int32Converter''
据我了解,这是因为csv中的field population是空的。我目前希望能够验证该字段并将其设置为 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;
}
}
}
我的映射 class 是
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,而且适用于任何类型,这是一个使用自定义泛型类型转换器的实现,如果转换失败,returns 类型的默认值。
这并不意味着您必须吞下或忽略异常。此转换器还将为您提供转换错误和违规值,以便您可以处理此无效数据。
我还添加了一个 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;
}
}
此致。
您可以使用 ClassMap
为 Population
提供默认值
public class Program
{
public static void Main(string[] args)
{
using (MemoryStream stream = new MemoryStream())
using (StreamWriter writer = new StreamWriter(stream))
using (StreamReader reader = new StreamReader(stream))
using (CsvReader csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
writer.WriteLine("CountryName,CountryCode,Continent,Population");
writer.WriteLine("TestName1,TestCode1,TestContinent1,");
writer.WriteLine("TestName2,TestCode2,TestContinent2,2");
writer.Flush();
stream.Position = 0;
csv.Configuration.RegisterClassMap<CountryMap>();
var countries = csv.GetRecords<Country>().ToList();
}
Console.ReadKey();
}
}
public class CountryMap : ClassMap<Country>
{
public CountryMap()
{
Map(m => m.CountryName);
Map(m => m.CountryCode);
Map(m => m.Continent);
Map(m => m.Population).Default(0);
}
}
public class Country
{
public string CountryName { get; set; }
public string CountryCode { get; set; }
public string Continent { get; set; }
public int Population { get; set; }
}
我目前正在使用 CSV 帮助程序读取 csv 文件的内容并将其输出到控制台。我已经安装了 csvHelper nuget 包。但是,当我 运行 代码时,出现以下错误:
CsvHelper.TypeConversion.TypeConverterException: '无法进行转换。 文本: '' 会员类型: 类型转换器:'CsvHelper.TypeConversion.Int32Converter''
据我了解,这是因为csv中的field population是空的。我目前希望能够验证该字段并将其设置为 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;
}
}
}
我的映射 class 是
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,而且适用于任何类型,这是一个使用自定义泛型类型转换器的实现,如果转换失败,returns 类型的默认值。
这并不意味着您必须吞下或忽略异常。此转换器还将为您提供转换错误和违规值,以便您可以处理此无效数据。
我还添加了一个 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;
}
}
此致。
您可以使用 ClassMap
为 Population
public class Program
{
public static void Main(string[] args)
{
using (MemoryStream stream = new MemoryStream())
using (StreamWriter writer = new StreamWriter(stream))
using (StreamReader reader = new StreamReader(stream))
using (CsvReader csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
writer.WriteLine("CountryName,CountryCode,Continent,Population");
writer.WriteLine("TestName1,TestCode1,TestContinent1,");
writer.WriteLine("TestName2,TestCode2,TestContinent2,2");
writer.Flush();
stream.Position = 0;
csv.Configuration.RegisterClassMap<CountryMap>();
var countries = csv.GetRecords<Country>().ToList();
}
Console.ReadKey();
}
}
public class CountryMap : ClassMap<Country>
{
public CountryMap()
{
Map(m => m.CountryName);
Map(m => m.CountryCode);
Map(m => m.Continent);
Map(m => m.Population).Default(0);
}
}
public class Country
{
public string CountryName { get; set; }
public string CountryCode { get; set; }
public string Continent { get; set; }
public int Population { get; set; }
}