How can one to dynamically parse a CSV file using C# and the Smart Format Detector in FileHelpers 3.1?

*爱你&永不变心* 提交于 2019-12-22 15:00:49

问题


As per in this FileHelpers 3.1 example, you can automatically detect a CSV file format using the FileHelpers.Detection.SmartFormatDetector class.

But the example goes no further. How do you use this information to dynamically parse a CSV file? It must have something to do with the DelimitedFileEngine but I cannot see how.

Update:

I figured out a possible way but had to resort to using reflection (which does not feel right). Is there another/better way? Maybe using System.Dynamic? Anyway, here is the code I have so far, it ain't pretty but it works:

        // 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();
        }

回答1:


As I use the SmartFormatDetector to determine the exact format of the incoming Delimited files you can use following appoach:

    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();
    }

This is an approach I use in a project, where I only know that I have to process Delimited files of multiple types.

Attention: I noticed that with the files I recieved the SmartFormatDetector has a problem with tab delimiter. Maybe this should be considered.

Disclaimer: This code is not perfected but in a usable state. Modification and/or refactoring is adviced.



来源:https://stackoverflow.com/questions/32507704/how-can-one-to-dynamically-parse-a-csv-file-using-c-sharp-and-the-smart-format-d

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!