سؤال

أدرك أن هذا هو مبتدئ السؤال, ولكن أنا أبحث عن حل بسيط - يبدو أنه يجب أن يكون هناك واحد.

ما هي أفضل طريقة استيراد ملف CSV إلى كتابة بشدة بنية البيانات ؟ مرة أخرى بسيطة = أفضل.

هل كانت مفيدة؟

المحلول

نصائح أخرى

مايكروسوفت TextFieldParser مستقر يلي RFC 4180 بالنسبة ملفات CSV.لا يمكن تأجيل Microsoft.VisualBasic الاسم;إنه مكون قياسي في .NET Framework, فقط إضافة إشارة إلى العالمية Microsoft.VisualBasic الجمعية.

إذا كنت تجميع ويندوز (مقابل أحادية) و لا توقع الحاجة إلى تحليل "كسر" (غير متوافقة مع RFC) ملفات CSV ، فإن هذا سيكون الخيار الواضح ، كما أنها حرة غير مقيدة ، مستقرة ، ودعم ، ومعظمها لا يمكن أن يقال عن FileHelpers.

انظر أيضا: كيفية:قراءة من بفواصل نص الملفات في Visual Basic بالنسبة VB المثال التعليمات البرمجية.

استخدام OleDB الصدد.

String sConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\InputDirectory\\;Extended Properties='text;HDR=Yes;FMT=Delimited'";
OleDbConnection objConn = new OleDbConnection(sConnectionString);
objConn.Open();
DataTable dt = new DataTable();
OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM file.csv", objConn);
OleDbDataAdapter objAdapter1 = new OleDbDataAdapter();
objAdapter1.SelectCommand = objCmdSelect;
objAdapter1.Fill(dt);
objConn.Close();

إذا كنت تتوقع سيناريوهات معقدة إلى حد ما CSV تحليل ، لا أعتقد حتى يصل المتداول الخاصة بنا محلل.هناك الكثير من أدوات ممتازة هناك مثل FileHelpers, أو حتى تلك التي من CodeProject.

هذه النقطة هي مشكلة شائعة و يمكن الرهان على أن الكثير من مطوري البرمجيات فعلا فكرت و حل هذه المشكلة.

براين يعطي الحل لطيفة تحويله إلى كتابتها بقوة المجموعة.

معظم CSV تحليل أساليب معينة لا تأخذ في الاعتبار الهروب الحقول أو بعض الخفايا من ملفات CSV (مثل التشذيب الحقول).هنا هو رمز وأنا شخصيا استخدام.انها قليلا الخام حول الحواف الى حد كبير قد لا عن الخطأ.

public static IList<IList<string>> Parse(string content)
{
    IList<IList<string>> records = new List<IList<string>>();

    StringReader stringReader = new StringReader(content);

    bool inQoutedString = false;
    IList<string> record = new List<string>();
    StringBuilder fieldBuilder = new StringBuilder();
    while (stringReader.Peek() != -1)
    {
        char readChar = (char)stringReader.Read();

        if (readChar == '\n' || (readChar == '\r' && stringReader.Peek() == '\n'))
        {
            // If it's a \r\n combo consume the \n part and throw it away.
            if (readChar == '\r')
            {
                stringReader.Read();
            }

            if (inQoutedString)
            {
                if (readChar == '\r')
                {
                    fieldBuilder.Append('\r');
                }
                fieldBuilder.Append('\n');
            }
            else
            {
                record.Add(fieldBuilder.ToString().TrimEnd());
                fieldBuilder = new StringBuilder();

                records.Add(record);
                record = new List<string>();

                inQoutedString = false;
            }
        }
        else if (fieldBuilder.Length == 0 && !inQoutedString)
        {
            if (char.IsWhiteSpace(readChar))
            {
                // Ignore leading whitespace
            }
            else if (readChar == '"')
            {
                inQoutedString = true;
            }
            else if (readChar == ',')
            {
                record.Add(fieldBuilder.ToString().TrimEnd());
                fieldBuilder = new StringBuilder();
            }
            else
            {
                fieldBuilder.Append(readChar);
            }
        }
        else if (readChar == ',')
        {
            if (inQoutedString)
            {
                fieldBuilder.Append(',');
            }
            else
            {
                record.Add(fieldBuilder.ToString().TrimEnd());
                fieldBuilder = new StringBuilder();
            }
        }
        else if (readChar == '"')
        {
            if (inQoutedString)
            {
                if (stringReader.Peek() == '"')
                {
                    stringReader.Read();
                    fieldBuilder.Append('"');
                }
                else
                {
                    inQoutedString = false;
                }
            }
            else
            {
                fieldBuilder.Append(readChar);
            }
        }
        else
        {
            fieldBuilder.Append(readChar);
        }
    }
    record.Add(fieldBuilder.ToString().TrimEnd());
    records.Add(record);

    return records;
}

لاحظ أن هذا لا التعامل مع حافة حالة من المجالات لا يجري deliminated من علامات الاقتباس المزدوجة ، ولكن meerley وجود سلسلة مقتبسة داخله.انظر هذا المنصب قليلا من أفضل expanation وكذلك بعض الروابط لبعض السليم المكتبات.

أنا أتفق مع @NotMyself. FileHelpers هو اختبار جيد ويتعامل مع جميع أنواع الحالات الحافة التي في نهاية المطاف سوف تضطر إلى التعامل مع إذا كنت تفعل ذلك بنفسك.نلقي نظرة على ما FileHelpers لا فقط الكتابة الخاصة بك إذا كنت متأكدا تماما من أنه إما (1) أنك لن تحتاج إلى التعامل مع الحالات حافة FileHelpers ، أو (2) كنت أحب الكتابة في هذا النوع من الاشياء ستكون بسعادة غامرة عندما تحتاج إلى تحليل مثل هذه الاشياء:

1"بيل","سميث","مشرف" "لا تعليق"

2 , 'دريك,' , 'أومالي',"بواب ،

عفوا, أنا لا نقلا و أنا على سطر جديد!

كنت أشعر بالملل لذا عدلت بعض الاشياء كتبت.انها محاولة لتغليف تحليل في OO طريقة whle خفض كمية التكرار من خلال الملف ، إلا أنها تتكرر مرة واحدة في أعلى foreach.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.IO;

namespace ConsoleApplication1
{
    class Program
    {

        static void Main(string[] args)
        {

            // usage:

            // note this wont run as getting streams is not Implemented

            // but will get you started

            CSVFileParser fileParser = new CSVFileParser();

            // TO Do:  configure fileparser

            PersonParser personParser = new PersonParser(fileParser);

            List<Person> persons = new List<Person>();
            // if the file is large and there is a good way to limit
            // without having to reparse the whole file you can use a 
            // linq query if you desire
            foreach (Person person in personParser.GetPersons())
            {
                persons.Add(person);
            }

            // now we have a list of Person objects
        }
    }

    public abstract  class CSVParser 
    {

        protected String[] deliniators = { "," };

        protected internal IEnumerable<String[]> GetRecords()
        {

            Stream stream = GetStream();
            StreamReader reader = new StreamReader(stream);

            String[] aRecord;
            while (!reader.EndOfStream)
            {
                  aRecord = reader.ReadLine().Split(deliniators,
                   StringSplitOptions.None);

                yield return aRecord;
            }

        }

        protected abstract Stream GetStream(); 

    }

    public class CSVFileParser : CSVParser
    {
        // to do: add logic to get a stream from a file

        protected override Stream GetStream()
        {
            throw new NotImplementedException();
        } 
    }

    public class CSVWebParser : CSVParser
    {
        // to do: add logic to get a stream from a web request

        protected override Stream GetStream()
        {
            throw new NotImplementedException();
        }
    }

    public class Person
    {
        public String Name { get; set; }
        public String Address { get; set; }
        public DateTime DOB { get; set; }
    }

    public class PersonParser 
    {

        public PersonParser(CSVParser parser)
        {
            this.Parser = parser;
        }

        public CSVParser Parser { get; set; }

        public  IEnumerable<Person> GetPersons()
        {
            foreach (String[] record in this.Parser.GetRecords())
            {
                yield return new Person()
                {
                    Name = record[0],
                    Address = record[1],
                    DOB = DateTime.Parse(record[2]),
                };
            }
        }
    }
}

هناك نوعان من المواد على CodeProject التي توفر رمز حل واحد يستخدم StreamReader واحد الواردات البيانات CSV باستخدام مايكروسوفت النص سائق.

جيد طريقة بسيطة للقيام بذلك هو فتح الملف و قراءة كل سطر في صفيف ، قائمة مرتبطة البيانات الهيكل الخاص في الاختيار.كن حذرا حول التعامل مع السطر الأول على الرغم من.

قد يكون هذا فوق رأسك, ولكن يبدو أن هناك وسيلة مباشرة للوصول إليها فضلا باستخدام سلسلة الاتصال.

لماذا لا نحاول استخدام بيثون بدلا من C# أو VB?لديها لطيفة CSV وحدة لاستيراد أن يفعل كل رفع الأحمال الثقيلة بالنسبة لك.

اضطررت لاستخدام CSV محلل في .صافي لمشروع هذا الصيف و استقر على Microsoft Jet النص السائق.يمكنك تحديد مجلد استخدام سلسلة اتصال ، ثم الاستعلام ملف باستخدام عبارة SQL Select.يمكنك تحديد قوية أنواع استخدام المخطط.ini.أنا لم أفعل هذا في البداية, ولكن بعد ذلك كنت الحصول على نتائج سيئة حيث نوع البيانات لم تكن واضحة على الفور ، مثل أرقام IP أو إدخال مثل "XYQ 3.9 SP1".

واحد الحد ركضت إلى أنه لا يمكن التعامل مع أسماء الأعمدة فوق 64 حرفا ؛ ذلك باقتطاع.هذا لا ينبغي أن يكون مشكلة ، إلا أنني كنت أتعامل مع مصمم ضعيف جدا إدخال البيانات.تقوم بإرجاع ADO.NET DataSet.

كان هذا هو أفضل حل وجدته.سأكون حذرا من المتداول بلدي CSV محلل, منذ أنا ربما يغيب عن بعض من نهاية الحالات, و لم أجد أي الحرة الأخرى CSV تحليل حزم .صافي هناك.

تحرير:أيضا, يمكن أن يكون هناك سوى واحد مخطط.ini في الدليل ، لذا حيوي إلحاق إليه بقوة اكتب حاجة الأعمدة.فإنه سيتم فقط بقوة من نوع الأعمدة المحددة ، ونستنتج أي غير محدد مجال.أنا حقا عن تقديره هذه ، كما كان التعامل مع استيراد السائل 70+ عمود CSV و لم ترغب في تحديد كل عمود, فقط الفاسقة منها.

كتبت في بعض التعليمات البرمجية.النتيجة في datagridviewer تبدو جيدة.فإنه يوزع سطر واحد من النص إلى arraylist من الكائنات.

    enum quotestatus
    {
        none,
        firstquote,
        secondquote
    }
    public static System.Collections.ArrayList Parse(string line,string delimiter)
    {        
        System.Collections.ArrayList ar = new System.Collections.ArrayList();
        StringBuilder field = new StringBuilder();
        quotestatus status = quotestatus.none;
        foreach (char ch in line.ToCharArray())
        {                                
            string chOmsch = "char";
            if (ch == Convert.ToChar(delimiter))
            {
                if (status== quotestatus.firstquote)
                {
                    chOmsch = "char";
                }                         
                else
                {
                    chOmsch = "delimiter";                    
                }                    
            }

            if (ch == Convert.ToChar(34))
            {
                chOmsch = "quotes";           
                if (status == quotestatus.firstquote)
                {
                    status = quotestatus.secondquote;
                }
                if (status == quotestatus.none )
                {
                    status = quotestatus.firstquote;
                }
            }

            switch (chOmsch)
            {
                case "char":
                    field.Append(ch);
                    break;
                case "delimiter":                        
                    ar.Add(field.ToString());
                    field.Clear();
                    break;
                case "quotes":
                    if (status==quotestatus.firstquote)
                    {
                        field.Clear();                            
                    }
                    if (status== quotestatus.secondquote)
                    {                                                                           
                            status =quotestatus.none;                                
                    }                    
                    break;
            }
        }
        if (field.Length != 0)            
        {
            ar.Add(field.ToString());                
        }           
        return ar;
    }

إذا كنت يمكن أن تضمن أنه لا توجد فواصل في البيانات ، ثم أبسط طريقة ربما يكون استخدام السلسلة.تقسيم.

على سبيل المثال:

String[] values = myString.Split(',');
myObject.StringField = values[0];
myObject.IntField = Int32.Parse(values[1]);

قد يكون هناك مكتبات يمكن استخدامها للمساعدة ، ولكن هذا ربما بسيطة كما يمكنك الحصول عليها.فقط تأكد من أنك لا يمكن أن يكون الفواصل في البيانات وإلا سوف تحتاج إلى تحليل ذلك أفضل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top