[C#] एक .NET डेटाटेबल में एक CSV फ़ाइल को कैसे पढ़ा जाए


Answers

मैं OleDb प्रदाता का उपयोग कर रहा हूं। हालांकि, यदि आप उन पंक्तियों में पढ़ रहे हैं जिनमें संख्यात्मक मान हैं लेकिन आप उन्हें टेक्स्ट के रूप में मानना ​​चाहते हैं तो इसमें समस्याएं हैं। हालांकि, आप schema.ini फ़ाइल बनाकर उस समस्या को हल कर सकते हैं। यहां मेरी विधि का उपयोग किया गया है:

// using System.Data;
// using System.Data.OleDb;
// using System.Globalization;
// using System.IO;

static DataTable GetDataTableFromCsv(string path, bool isFirstRowHeader)
{
    string header = isFirstRowHeader ? "Yes" : "No";

    string pathOnly = Path.GetDirectoryName(path);
    string fileName = Path.GetFileName(path);

    string sql = @"SELECT * FROM [" + fileName + "]";

    using(OleDbConnection connection = new OleDbConnection(
              @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + pathOnly + 
              ";Extended Properties=\"Text;HDR=" + header + "\""))
    using(OleDbCommand command = new OleDbCommand(sql, connection))
    using(OleDbDataAdapter adapter = new OleDbDataAdapter(command))
    {
        DataTable dataTable = new DataTable();
        dataTable.Locale = CultureInfo.CurrentCulture;
        adapter.Fill(dataTable);
        return dataTable;
    }
}
Question

मैं एक CSV फ़ाइल को System.Data.DataTable में कैसे लोड कर सकता हूं, CSV फ़ाइल के आधार पर डेटाटेबल बना सकता हूं?

क्या नियमित ADO.net कार्यक्षमता इसकी अनुमति देती है?




श्री चकबेविट से संशोधित

कार्य समाधान:

string CSVFilePathName = APP_PATH + "Facilities.csv";
string[] Lines = File.ReadAllLines(CSVFilePathName);
string[] Fields;
Fields = Lines[0].Split(new char[] { ',' });
int Cols = Fields.GetLength(0);
DataTable dt = new DataTable();
//1st row must be column names; force lower case to ensure matching later on.
for (int i = 0; i < Cols-1; i++)
        dt.Columns.Add(Fields[i].ToLower(), typeof(string));
DataRow Row;
for (int i = 0; i < Lines.GetLength(0)-1; i++)
{
        Fields = Lines[i].Split(new char[] { ',' });
        Row = dt.NewRow();
        for (int f = 0; f < Cols-1; f++)
                Row[f] = Fields[f];
        dt.Rows.Add(Row);
}



आप में से उन लोगों के लिए जो बाहरी पुस्तकालय का उपयोग नहीं करना चाहते हैं, और ओलेडीबी का उपयोग न करना पसंद करते हैं, नीचे दिए गए उदाहरण को देखें। जो कुछ भी मैंने पाया वह ओलेडीबी, बाहरी पुस्तकालय, या बस अल्पविराम के आधार पर विभाजित था! मेरे मामले के लिए ओलेडीबी काम नहीं कर रहा था इसलिए मुझे कुछ अलग चाहिए।

मुझे मार्कजे द्वारा एक लेख मिला जो माइक्रोसॉफ्ट का संदर्भ देता है। विज़ुअल बेसिक.फाइलियो। टेक्स्टफिल्ल्ड पार्सर विधि जैसा कि here देखा गया here । लेख वीबी में लिखा गया है और एक डाटाटेबल वापस नहीं करता है, इसलिए नीचे मेरा उदाहरण देखें।

public static DataTable LoadCSV(string path, bool hasHeader)
    {
        DataTable dt = new DataTable();

        using (var MyReader = new Microsoft.VisualBasic.FileIO.TextFieldParser(path))
        {
            MyReader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited;
            MyReader.Delimiters = new String[] { "," };

            string[] currentRow;

            //'Loop through all of the fields in the file.  
            //'If any lines are corrupt, report an error and continue parsing.  
            bool firstRow = true;
            while (!MyReader.EndOfData)
            {
                try
                {
                    currentRow = MyReader.ReadFields();

                    //Add the header columns
                    if (hasHeader && firstRow)
                    {
                        foreach (string c in currentRow)
                        {
                            dt.Columns.Add(c, typeof(string));
                        }

                        firstRow = false;
                        continue;
                    }

                    //Create a new row
                    DataRow dr = dt.NewRow();
                    dt.Rows.Add(dr);

                    //Loop thru the current line and fill the data out
                    for(int c = 0; c < currentRow.Count(); c++)
                    {
                        dr[c] = currentRow[c];
                    }
                }
                catch (Microsoft.VisualBasic.FileIO.MalformedLineException ex)
                {
                    //Handle the exception here
                }
            }
        }

        return dt;
    }



यह वह कोड है जिसका मैं उपयोग करता हूं लेकिन आपके ऐप्स को नेट वर्जन 3.5 के साथ चलाना चाहिए

private void txtRead_Click(object sender, EventArgs e)
        {
           // var filename = @"d:\shiptest.txt";

            openFileDialog1.InitialDirectory = "d:\\";
            openFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
            DialogResult result = openFileDialog1.ShowDialog();
            if (result == DialogResult.OK)
            {
                if (openFileDialog1.FileName != "")
                {
                    var reader = ReadAsLines(openFileDialog1.FileName);

                    var data = new DataTable();

                    //this assume the first record is filled with the column names
                    var headers = reader.First().Split(',');
                    foreach (var header in headers)
                    {
                        data.Columns.Add(header);
                    }

                    var records = reader.Skip(1);
                    foreach (var record in records)
                    {
                        data.Rows.Add(record.Split(','));
                    }

                    dgList.DataSource = data;
                }
            }
        }

        static IEnumerable<string> ReadAsLines(string filename)
        {
            using (StreamReader reader = new StreamReader(filename))
                while (!reader.EndOfStream)
                    yield return reader.ReadLine();
        }



public class Csv
{
    public static DataTable DataSetGet(string filename, string separatorChar, out List<string> errors)
    {
        errors = new List<string>();
        var table = new DataTable("StringLocalization");
        using (var sr = new StreamReader(filename, Encoding.Default))
        {
            string line;
            var i = 0;
            while (sr.Peek() >= 0)
            {
                try
                {
                    line = sr.ReadLine();
                    if (string.IsNullOrEmpty(line)) continue;
                    var values = line.Split(new[] {separatorChar}, StringSplitOptions.None);
                    var row = table.NewRow();
                    for (var colNum = 0; colNum < values.Length; colNum++)
                    {
                        var value = values[colNum];
                        if (i == 0)
                        {
                            table.Columns.Add(value, typeof (String));
                        }
                        else
                        {
                            row[table.Columns[colNum]] = value;
                        }
                    }
                    if (i != 0) table.Rows.Add(row);
                }
                catch(Exception ex)
                {
                    errors.Add(ex.Message);
                }
                i++;
            }
        }
        return table;
    }
}



अरे यह 100% काम कर रहा है

  public static DataTable ConvertCSVtoDataTable(string strFilePath)
  {
    DataTable dt = new DataTable();
    using (StreamReader sr = new StreamReader(strFilePath))
    {
        string[] headers = sr.ReadLine().Split(',');
        foreach (string header in headers)
        {
            dt.Columns.Add(header);
        }
        while (!sr.EndOfStream)
        {
            string[] rows = sr.ReadLine().Split(',');
            DataRow dr = dt.NewRow();
            for (int i = 0; i < headers.Length; i++)
            {
                dr[i] = rows[i];
            }
            dt.Rows.Add(dr);
        }

    }


    return dt;
   }

सीएसवी छवि

डेटा टेबल आयात किया गया




इस पर अपना खुद का स्पिन जोड़ने का विरोध नहीं कर सकता। अतीत में जो मैंने उपयोग किया है उससे यह इतना बेहतर और अधिक कॉम्पैक्ट है।

यह समाधान:

  • डेटाबेस ड्राइवर या तृतीय पक्ष लाइब्रेरी पर निर्भर नहीं है।
  • डुप्लिकेट कॉलम नामों पर असफल नहीं होगा
  • डेटा में अल्पविराम संभालता है
  • किसी भी delimiter संभालती है, न केवल अल्पविराम (हालांकि यह डिफ़ॉल्ट है)

यहां मैं ये आया हूं:

  Public Function ToDataTable(FileName As String, Optional Delimiter As String = ",") As DataTable
    ToDataTable = New DataTable
    Using TextFieldParser As New Microsoft.VisualBasic.FileIO.TextFieldParser(FileName) With
      {.HasFieldsEnclosedInQuotes = True, .TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited, .TrimWhiteSpace = True}
      With TextFieldParser
        .SetDelimiters({Delimiter})
        .ReadFields.ToList.Unique.ForEach(Sub(x) ToDataTable.Columns.Add(x))
        ToDataTable.Columns.Cast(Of DataColumn).ToList.ForEach(Sub(x) x.AllowDBNull = True)
        Do Until .EndOfData
          ToDataTable.Rows.Add(.ReadFields.Select(Function(x) Text.BlankToNothing(x)).ToArray)
        Loop
      End With
    End Using
  End Function

स्ट्रिंग्स की सूची में अनन्य संख्याओं को कैसे जोड़ना है, यह मेरे उत्तर के रूप में पाया जाने वाला डुप्लिकेट कॉलम नामों को संभालने के लिए एक विस्तार विधि ( Unique ) पर निर्भर करता है

और यहां BlankToNothing सहायक कार्य नहीं:

  Public Function BlankToNothing(ByVal Value As String) As Object 
    If String.IsNullOrEmpty(Value) Then Return Nothing
    Return Value
  End Function



मैं कोड के इस टुकड़े में आया जो सीएसवी फ़ाइल को पार्स करने के लिए लिंक और रेगेक्स का उपयोग करता है। रिफायरिंग आलेख अब डेढ़ साल से अधिक है, लेकिन इस से लिंक (और रेगेक्स) का उपयोग करके सीएसवी को पार्स करने के लिए एक साफ तरीके से नहीं आया है। चेतावनी यहां लागू रेगेक्स है जिसे अल्पविराम सीमांकित फाइलों के लिए है (कोट्स के अंदर कॉमा का पता लगाएगा!) और यह हेडर को अच्छी तरह से नहीं ले सकता है, लेकिन इन पर काबू पाने का एक तरीका है)। एक चोटी ले लो:

Dim lines As String() = System.IO.File.ReadAllLines(strCustomerFile)
Dim pattern As String = ",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"
Dim r As System.Text.RegularExpressions.Regex = New System.Text.RegularExpressions.Regex(pattern)
Dim custs = From line In lines _
            Let data = r.Split(line) _
                Select New With {.custnmbr = data(0), _
                                 .custname = data(1)}
For Each cust In custs
    strCUSTNMBR = Replace(cust.custnmbr, Chr(34), "")
    strCUSTNAME = Replace(cust.custname, Chr(34), "")
Next



Links