Parsing 如何使用C#和FileHelpers 3.1中的智能格式检测器动态解析CSV文件?

Parsing 如何使用C#和FileHelpers 3.1中的智能格式检测器动态解析CSV文件?,parsing,csv,dynamic,flat-file,filehelpers,Parsing,Csv,Dynamic,Flat File,Filehelpers,如中所述,您可以使用FileHelpers.Detection.SmartFormatDetector类自动检测CSV文件格式 但这个例子并没有进一步说明。如何使用此信息动态解析CSV文件?这一定和内燃机有关,但我看不出是怎么回事 更新: 我想出了一个可能的方法,但不得不求助于使用反射(这感觉不太对)。还有其他/更好的方法吗?也许使用系统,动态?不管怎么说,这是我到目前为止的代码,虽然不漂亮,但很有效: // follows on from smart detector exam

如中所述,您可以使用FileHelpers.Detection.SmartFormatDetector类自动检测CSV文件格式

但这个例子并没有进一步说明。如何使用此信息动态解析CSV文件?这一定和内燃机有关,但我看不出是怎么回事

更新:

我想出了一个可能的方法,但不得不求助于使用反射(这感觉不太对)。还有其他/更好的方法吗?也许使用系统,动态?不管怎么说,这是我到目前为止的代码,虽然不漂亮,但很有效:

        // follows on from smart detector example

        FileHelpers.Detection.RecordFormatInfo lDetectedFormat = formats[0];

        Type lDetectedClass = lDetectedFormat.ClassBuilderAsDelimited.CreateRecordClass();

        List<FieldInfo> lFieldInfoList = new List<FieldInfo>(lDetectedFormat.ClassBuilderAsDelimited.FieldCount);
        foreach (FileHelpers.Dynamic.DelimitedFieldBuilder lField in lDetectedFormat.ClassBuilderAsDelimited.Fields)
            lFieldInfoList.Add(lDetectedClass.GetField(lField.FieldName));

        FileHelperAsyncEngine lFileEngine = new FileHelperAsyncEngine(lDetectedClass);
        int lRecNo = 0;
        lFileEngine.BeginReadFile(cReadingsFile);
        try
        {
            while (true)
            {
                object lRec = lFileEngine.ReadNext();
                if (lRec == null)
                    break;

                Trace.WriteLine("Record " + lRecNo);
                lFieldInfoList.ForEach(f => Trace.WriteLine("   " + f.Name + " = " + f.GetValue(lRec)));

                lRecNo++;
            }
        }
        finally
        {
            lFileEngine.Close();
        }
//以下是智能探测器示例
FileHelpers.Detection.RecordFormatInfo lDetectedFormat=格式[0];
键入lDetectedClass=lDetectedFormat.ClassBuilderAsDelimited.CreateRecordClass();
List lFieldInfoList=新列表(lDetectedFormat.ClassBuilderAsDelimited.FieldCount);
foreach(文件helpers.Dynamic.DelimitedFieldBuilder lField采用lDetectedFormat.ClassBuilderDelimited.Fields格式)
添加(lDetectedClass.GetField(lField.FieldName));
FileHelperAsyncEngine lFileEngine=新的FileHelperAsyncEngine(lDetectedClass);
int-lRecNo=0;
lFileEngine.BeginReadFile(creadingfile);
尝试
{
while(true)
{
对象lRec=lFileEngine.ReadNext();
如果(lRec==null)
打破
Trace.WriteLine(“记录”+lRecNo);
lFieldInfoList.ForEach(f=>Trace.WriteLine(“+f.Name+”=“+f.GetValue(lRec));
lRecNo++;
}
}
最后
{
lFileEngine.Close();
}

当我使用SmartFormatDetector确定传入分隔文件的确切格式时,您可以使用以下方法:

    private DelimitedClassBuilder GetFormat(string file)
    {
        var detector = new FileHelpers.Detection.SmartFormatDetector();
        var format = detector.DetectFileFormat(file);

        return format.First().ClassBuilderAsDelimited;
    }

    private List<T> ConvertFile2Objects<T>(string file, out DelimitedFileEngine engine)
    {
        var format = GetSeperator(file); // Get Here your FormatInfo
        engine = new DelimitedFileEngine(typeof(T)); //define your DelimitdFileEngine

        //set some Properties of the engine with what you need
        engine.ErrorMode = ErrorMode.SaveAndContinue; //optional
        engine.Options.Delimiter = format.Delimiter;
        engine.Options.IgnoreFirstLines = format.IgnoreFirstLines;
        engine.Options.IgnoreLastLines = format.IgnoreLastLines;
        //process
        var ret = engine.ReadFileAsList(file);
        this.errorCount = engine.ErrorManager.ErrorCount;
        var err = engine.ErrorManager.Errors;
        engine.ErrorManager.SaveErrors("errors.out");
        //return records do here what you need
        return ret.Cast<T>().ToList();
    }
private DelimitedClassBuilder GetFormat(字符串文件)
{
var detector=new FileHelpers.Detection.SmartFormatDetector();
var format=detector.DetectFileFormat(文件);
返回格式.First().ClassBuilderAsDelimited;
}
私有列表ConvertFile2对象(字符串文件,外部分隔符dFileEngine引擎)
{
var format=getseparator(file);//在这里获取您的FormatInfo
engine=new DelimitedFileEngine(typeof(T));//定义您的DelimitedFileEngine
//根据需要设置引擎的某些属性
engine.ErrorMode=ErrorMode.SaveAndContinue;//可选
engine.Options.Delimiter=格式.Delimiter;
engine.Options.IgnoreFirstLines=format.IgnoreFirstLines;
engine.Options.IgnoreLastLines=format.IgnoreLastLines;
//过程
var ret=engine.ReadFileAsList(文件);
this.errorCount=engine.ErrorManager.errorCount;
var err=engine.ErrorManager.Errors;
engine.ErrorManager.SaveErrors(“errors.out”);
//退货记录可以满足您的需要
返回ret.Cast().ToList();
}
这是我在项目中使用的一种方法,我只知道我必须处理多种类型的分隔文件

注意: 我注意到,对于我收到的文件,SmartFormatDetector的制表符分隔符有问题。也许这应该考虑一下


免责声明:此代码不完善,但处于可用状态。建议进行修改和/或重构。

动态不只是意味着它使用了反射和后期绑定吗?反射总是对性能造成影响,因此唯一的其他方法是使用Linq表达式