Cách đọc tệp CSV vào .NET Datable


150
55
Trịnh Anh Khuê
10 năm trước

Làm cách nào tôi có thể tải tệp CSV vào một System.Data.DataTable, tạo dữ liệu dựa trên tệp CSV?

Chức năng ADO.net thông thường có cho phép điều này không?

Hữu ích 150 Yêu thích 55 Chia sẻ Viết bình luận 2
Không hữu ích

Làm thế nào điều này có thể 'lạc đề'? Đó là một câu hỏi cụ thể và 100 người thấy nó hữu ích

Hữu ích 13 · Không hữu ích · Trả lời 0

@Ryan: Quả thật tôi nói với bạn ... Người điều hành StackOverflow là một người nuôi dưỡng vipers. Đằng sau tôi, người điều hành StackOverflow!

Hữu ích 8 · Không hữu ích · Trả lời 0

19 Trả lời


83
Trịnh Thành Doanh
10 năm trước

Đây là một lớp tuyệt vời sẽ sao chép dữ liệu CSV vào một cơ sở dữ liệu bằng cách sử dụng cấu trúc của dữ liệu để tạo DataTable:

Trình phân tích cú pháp chung di động và hiệu quả cho các tệp phẳng

Thật dễ dàng để cấu hình và dễ sử dụng. Tôi mong bạn hãy xem.

Hữu ích 83 Trả lời hay nhất Chia sẻ Viết bình luận 3
Không hữu ích

@gonzobrains - Có lẽ là không; giả định cơ bản của tệp CSV là cấu trúc dữ liệu hình chữ nhật dựa trên một bộ tiêu đề cột duy nhất được chỉ định trong dòng đầu tiên. Những gì bạn dường như là dữ liệu phân biệt bằng dấu phẩy, được phân tách bằng dấu phẩy, yêu cầu "ETL" tinh vi hơn để phân tích cú pháp từ tệp thành các phiên bản đối tượng của các loại khác nhau (có thể bao gồm DataRows của các DataTables khác nhau).

Hữu ích 1 · Không hữu ích · Trả lời 0

Tuyệt vời thực sự. Nó hoạt động hoàn hảo cho tôi ra khỏi hộp, thậm chí không cần đọc tài liệu.

Hữu ích 0 · Không hữu ích · Trả lời 0

Điều này có hoạt động trên các tệp CSV trong đó mỗi hàng có thể có cấu trúc khác nhau không? Tôi có một tệp nhật ký với các loại sự kiện đã ghi khác nhau cần được tách ra thành nhiều bảng.

Hữu ích 0 · Không hữu ích · Trả lời 0

88
Phạm Duyên Nương
10 năm trước

Tôi đã được sử dụng OleDbnhà cung cấp. Tuy nhiên, nó có vấn đề nếu bạn đang đọc trong các hàng có giá trị số nhưng bạn muốn chúng được coi là văn bản. Tuy nhiên, bạn có thể khắc phục vấn đề đó bằng cách tạo một schema.initệp. Đây là phương pháp của tôi, tôi đã sử dụng:

// 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;
    }
}
Hữu ích 88 Chia sẻ Viết bình luận 5
Không hữu ích

Trong khi câu trả lời này sẽ có hiệu quả, tôi sẽ khuyên bạn nên chống lại nó. Bạn giới thiệu một phụ thuộc bên ngoài có thể xung đột với các cài đặt văn phòng khác trên cùng một máy (sử dụng Excel trên môi trường phát triển cục bộ của bạn?), Tùy thuộc vào các phiên bản được cài đặt. Có các gói NuGet ngoài kia (ExcelDataReader, CsvHelper) thực hiện việc này theo những cách hiệu quả hơn, di động hơn.

Hữu ích 2 · Không hữu ích · Trả lời 0

Cảm ơn cậu. Điều đó đã giúp tôi. Tôi đã có một tệp CSV trong đó dấu phẩy không chỉ là dấu phân cách, chúng ở khắp mọi nơi bên trong nhiều giá trị cột, do đó, việc tạo ra một biểu thức phân tách dòng là một thách thức. OleDbProvider đã suy luận chính xác lược đồ.

Hữu ích 0 · Không hữu ích · Trả lời 0

Việc thực hiện có ý nghĩa nhưng làm thế nào để chúng ta đối phó với các ô chứa các kiểu dữ liệu hỗn hợp. Ví dụ, 40C và vv?

Hữu ích 0 · Không hữu ích · Trả lời 0

GKED, nếu dữ liệu bạn đang đọc luôn có một tập hợp các cột và loại dự kiến ​​bạn có thể đặt trong cùng thư mục một tệp shema.ini cho biết thông tin của nhà cung cấp OleDb về các cột. Đây là một liên kết đến một bài viết của Microsoft cung cấp chi tiết về cách cấu trúc tệp. msdn.microsoft.com/en-us/l Library / từ

Hữu ích 0 · Không hữu ích · Trả lời 0

@ A.Mah - Chính xác thì ý bạn là gì? Điều này sử dụng nhà cung cấp OleDb tích hợp trong System.Data.dll. Bạn không cần phải cài đặt thêm bất kỳ "trình điều khiển" nào. Và tôi sẽ bị sốc trong thời đại ngày nay nếu bất kỳ cài đặt windows nào không cài đặt trình điều khiển Jet cơ bản. Đây là CSV của năm 1990 ....

Hữu ích 0 · Không hữu ích · Trả lời 0

40
Pham Hoang Anh
10 năm trước

Tôi đã quyết định sử dụng Csv Reader của Sebastien Lorion .

Đề xuất của Jay Riggs cũng là một giải pháp tuyệt vời, nhưng tôi không cần tất cả các tính năng mà Trình phân tích cú pháp chung của Andrew Rissing cung cấp.

CẬP NHẬT 25/10/2010

Sau khi sử dụng Csv Reader của Sebastien Lorion trong dự án của tôi trong gần một năm rưỡi, tôi đã thấy rằng nó đưa ra các ngoại lệ khi phân tích một số tệp csv mà tôi tin là được hình thành tốt.

Vì vậy, tôi đã chuyển sang Trình phân tích cú pháp chung của Andrew Rissing và có vẻ như nó đang hoạt động tốt hơn nhiều.

CẬP NHẬT ngày 22/9/2014

Ngày nay, tôi chủ yếu sử dụng phương pháp mở rộng này để đọc văn bản được phân tách:

https://github.com/Core-Techs/Common/blob/master/CoreTechs.Common/Text/DelrictTextExtensions.cs#L22

https://www.nuget.org/packages/CoreTechs.Common/

CẬP NHẬT 2/20/2015

Thí dụ:

var csv = @"Name, Age
Ronnie, 30
Mark, 40
Ace, 50";

TextReader reader = new StringReader(csv);
var table = new DataTable();
using(var it = reader.ReadCsvWithHeader().GetEnumerator())
{

    if (!it.MoveNext()) return;

    foreach (var k in it.Current.Keys)
        table.Columns.Add(k);

    do
    {
        var row = table.NewRow();
        foreach (var k in it.Current.Keys)
            row[k] = it.Current[k];

        table.Rows.Add(row);

    } while (it.MoveNext());
}
Hữu ích 40 Chia sẻ Viết bình luận 5
Không hữu ích

Tôi đồng ý rằng trình đọc CSV của Sebastien Lorien là tuyệt vời. Tôi sử dụng nó để xử lý CSV nặng, nhưng tôi cũng đã sử dụng Rissing của Andrew cho các công việc nhỏ và nó phục vụ tốt cho tôi. Chúc vui vẻ!

Hữu ích 0 · Không hữu ích · Trả lời 0

Làm cách nào tôi có thể sử dụng các lớp này để tải CSV vào DATATABLE?

Hữu ích 0 · Không hữu ích · Trả lời 0

Xem cập nhật.

Hữu ích 0 · Không hữu ích · Trả lời 0

Tôi đã thử điều này nhưng bộ sưu tập it.C Hiện tại. Bất kỳ suy nghĩ như tại sao?

Hữu ích 0 · Không hữu ích · Trả lời 0

Bạn có thể sử dụng nhiều ký tự phân cách?

Hữu ích 0 · Không hữu ích · Trả lời 0

28
Hoàng Việt Long
5 năm trước

Này nó hoạt động 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;
   }

Hình ảnh CSV

Bảng dữ liệu được nhập

Hữu ích 28 Chia sẻ Viết bình luận 5
Không hữu ích

Chỉ khi 100% đầu vào là tệp CSV đơn giản nhất (có thể đúng trong trường hợp của bạn).

Hữu ích 5 · Không hữu ích · Trả lời 0

Xem câu trả lời của tôi từ năm 2009.

Hữu ích 1 · Không hữu ích · Trả lời 0

Việc này ổn với tôi. rất cảm ơn

Hữu ích 1 · Không hữu ích · Trả lời 0

@ShivamSrivastava Tôi gặp lỗi ở hàng cuối cùng là bạn ở đó sau đó cung cấp cho bạn thông tin liên hệ khác

Hữu ích 1 · Không hữu ích · Trả lời 0

Bạn nói đúng. bạn nên sử dụng codeproject.com/Articles/9258/A-Fast-CSV-Reader (Lorion dll) Tôi đã thử nó hoạt động tốt.

Hữu ích 0 · Không hữu ích · Trả lời 0

13
Ngô Khánh Ngân
9 năm trước

Chúng tôi luôn sử dụng trình điều khiển Jet.OLEDB, cho đến khi chúng tôi bắt đầu chuyển sang các ứng dụng 64 bit. Microsoft đã không và sẽ không phát hành trình điều khiển Jet 64 bit. Đây là một giải pháp đơn giản mà chúng tôi đã đưa ra bằng cách sử dụng File.ReadAllLines và String.Split để đọc và phân tích tệp CSV và tải một DataTable theo cách thủ công. Như đã lưu ý ở trên, nó KHÔNG xử lý tình huống trong đó một trong các giá trị cột chứa dấu phẩy. Chúng tôi sử dụng phần lớn để đọc các tệp cấu hình tùy chỉnh - phần thú vị của việc sử dụng tệp CSV là chúng tôi có thể chỉnh sửa chúng trong Excel.

string CSVFilePathName = @"C:\test.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; i++)
    dt.Columns.Add(Fields[i].ToLower(), typeof(string));
DataRow Row;
for (int i = 1; i < Lines.GetLength(0); i++)
{
    Fields = Lines[i].Split(new char[] { ',' });
    Row = dt.NewRow();
    for (int f = 0; f < Cols; f++)
        Row[f] = Fields[f];
    dt.Rows.Add(Row);
}
Hữu ích 13 Chia sẻ Viết bình luận 0
Không hữu ích

8
Đặng Hoàng Anh
7 năm trước

đây là mã tôi sử dụng nhưng ứng dụng của bạn phải chạy với phiên bản thuần 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();
        }
Hữu ích 8 Chia sẻ Viết bình luận 1
Không hữu ích

Đây là khá nhiều những gì tôi muốn trình bày.

Hữu ích 0 · Không hữu ích · Trả lời 0

6
Trịnh Lan Anh
6 năm trước

Bạn có thể đạt được nó bằng cách sử dụng dll Microsoft.VisualBasic.FileIO.TextFieldParser trong C #

static void Main()
        {
            string csv_file_path=@"C:\Users\Administrator\Desktop\test.csv";

            DataTable csvData = GetDataTabletFromCSVFile(csv_file_path);

            Console.WriteLine("Rows count:" + csvData.Rows.Count);

            Console.ReadLine();
        }


private static DataTable GetDataTabletFromCSVFile(string csv_file_path)
        {
            DataTable csvData = new DataTable();

            try
            {

            using(TextFieldParser csvReader = new TextFieldParser(csv_file_path))
                {
                    csvReader.SetDelimiters(new string[] { "," });
                    csvReader.HasFieldsEnclosedInQuotes = true;
                    string[] colFields = csvReader.ReadFields();
                    foreach (string column in colFields)
                    {
                        DataColumn datecolumn = new DataColumn(column);
                        datecolumn.AllowDBNull = true;
                        csvData.Columns.Add(datecolumn);
                    }

                    while (!csvReader.EndOfData)
                    {
                        string[] fieldData = csvReader.ReadFields();
                        //Making empty value as null
                        for (int i = 0; i < fieldData.Length; i++)
                        {
                            if (fieldData[i] == "")
                            {
                                fieldData[i] = null;
                            }
                        }
                        csvData.Rows.Add(fieldData);
                    }
                }
            }
            catch (Exception ex)
            {
            }
            return csvData;
        }
Hữu ích 6 Chia sẻ Viết bình luận 2
Không hữu ích

Vui lòng không cố gắng phát minh lại bánh xe bằng xử lý CSV. Có rất nhiều lựa chọn thay thế nguồn mở tuyệt vời ngoài kia rất mạnh mẽ.

Hữu ích 0 · Không hữu ích · Trả lời 0

Cảm ơn Brad, mẹo hữu ích liên quan đến TextFieldParser để xử lý các trích dẫn được nhúng.

Hữu ích 0 · Không hữu ích · Trả lời 0

4
Vũ Bảo Khánh
8 năm trước

Tôi đã bắt gặp đoạn mã này sử dụng Linq và regex để phân tích tệp CSV. Bài viết giới thiệu hiện đã được hơn một năm rưỡi, nhưng chưa bắt gặp một cách gọn gàng hơn để phân tích CSV bằng Linq (và regex) hơn thế này. Thông báo trước là regex được áp dụng ở đây dành cho các tệp được phân tách bằng dấu phẩy (sẽ phát hiện dấu phẩy bên trong dấu ngoặc kép!) Và nó có thể không tốt cho các tiêu đề, nhưng có một cách để khắc phục những điều này). Lên đỉnh

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
Hữu ích 4 Chia sẻ Viết bình luận 0
Không hữu ích

3
Vũ Tuấn Hùng
7 năm trước

Tùy chọn tốt nhất mà tôi đã tìm thấy và nó giải quyết các vấn đề trong đó bạn có thể cài đặt các phiên bản Office khác nhau và các vấn đề 32/64 bit như Chuck Bevitt đã đề cập , là FileHelpers .

Nó có thể được thêm vào tài liệu tham khảo dự án của bạn bằng NuGet và nó cung cấp giải pháp một lớp:

CommonEngine.CsvToDataTable(path, "ImportRecord", ',', true);
Hữu ích 3 Chia sẻ Viết bình luận 2
Không hữu ích

Bạn có thể nói CommonEngine là gì không? Là NuGet giống với NuGet.Core. Tôi chỉ tìm thấy NuGet.Core trong tài liệu tham khảo

Hữu ích 0 · Không hữu ích · Trả lời 0

Đây là FileHelpers bạn cần. Nếu bạn có NuGet, hãy thêm nó với NuGet. Nếu không, chỉ cần thêm nó như là một hội đồng trong dự án của bạn. CommonEngine là một phần của FileHelpers.

Hữu ích 0 · Không hữu ích · Trả lời 0

3
Trần Anh Hoàng
7 năm trước

Đối với những người bạn muốn không sử dụng thư viện bên ngoài và không muốn sử dụng OleDB, hãy xem ví dụ bên dưới. Mọi thứ tôi tìm thấy là OleDB, thư viện bên ngoài hoặc đơn giản là phân tách dựa trên dấu phẩy! Đối với trường hợp của tôi, OleDB không hoạt động nên tôi muốn một cái gì đó khác biệt.

Tôi tìm thấy một bài viết của MarkJ đã tham chiếu phương pháp Microsoft.VisualBasic.FileIO.TextFieldParser như được thấy ở đây . Bài viết được viết bằng VB và không trả về dữ liệu, vì vậy hãy xem ví dụ của tôi dưới đây.

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;
    }
Hữu ích 3 Chia sẻ Viết bình luận 0
Không hữu ích

3
Phan Hồng Phát
5 năm trước

Câu trả lời rất cơ bản: nếu bạn không có một csv phức tạp có thể sử dụng hàm phân chia đơn giản thì điều này sẽ hoạt động tốt để nhập (lưu ý nhập này dưới dạng chuỗi, tôi sẽ chuyển đổi kiểu dữ liệu sau nếu tôi cần)

 private DataTable csvToDataTable(string fileName, char splitCharacter)
    {                
        StreamReader sr = new StreamReader(fileName);
        string myStringRow = sr.ReadLine();
        var rows = myStringRow.Split(splitCharacter);
        DataTable CsvData = new DataTable();
        foreach (string column in rows)
        {
            //creates the columns of new datatable based on first row of csv
            CsvData.Columns.Add(column);
        }
        myStringRow = sr.ReadLine();
        while (myStringRow != null)
        {
            //runs until string reader returns null and adds rows to dt 
            rows = myStringRow.Split(splitCharacter);
            CsvData.Rows.Add(rows);
            myStringRow = sr.ReadLine();
        }
        sr.Close();
        sr.Dispose();
        return CsvData;
    }

Phương thức của tôi nếu tôi đang nhập một bảng có dấu phân tách chuỗi [] và xử lý vấn đề trong đó dòng hiện tại tôi đang đọc có thể đã đi đến dòng tiếp theo trong tệp csv hoặc tệp văn bản <- IN trong trường hợp tôi muốn lặp cho đến khi tôi nhận được đến tổng số dòng trong hàng đầu tiên (cột)

public static DataTable ImportCSV(string fullPath, string[] sepString)
    {
        DataTable dt = new DataTable();
        using (StreamReader sr = new StreamReader(fullPath))
        {
           //stream uses using statement because it implements iDisposable
            string firstLine = sr.ReadLine();
            var headers = firstLine.Split(sepString, StringSplitOptions.None);
            foreach (var header in headers)
            {
               //create column headers
                dt.Columns.Add(header);
            }
            int columnInterval = headers.Count();
            string newLine = sr.ReadLine();
            while (newLine != null)
            {
                //loop adds each row to the datatable
                var fields = newLine.Split(sepString, StringSplitOptions.None); // csv delimiter    
                var currentLength = fields.Count();
                if (currentLength < columnInterval)
                {
                    while (currentLength < columnInterval)
                    {
                       //if the count of items in the row is less than the column row go to next line until count matches column number total
                        newLine += sr.ReadLine();
                        currentLength = newLine.Split(sepString, StringSplitOptions.None).Count();
                    }
                    fields = newLine.Split(sepString, StringSplitOptions.None);
                }
                if (currentLength > columnInterval)
                {  
                    //ideally never executes - but if csv row has too many separators, line is skipped
                    newLine = sr.ReadLine();
                    continue;
                }
                dt.Rows.Add(fields);
                newLine = sr.ReadLine();
            }
            sr.Close();
        }

        return dt;
    }
Hữu ích 3 Chia sẻ Viết bình luận 2
Không hữu ích

Rất vui vì bạn chưa khai báo các hàng dưới dạng chuỗi [].

Hữu ích 0 · Không hữu ích · Trả lời 0

@AnimalStyle bạn đúng - được cập nhật với phương thức mạnh hơn và các hàng được khai báo

Hữu ích 0 · Không hữu ích · Trả lời 0

3
Dương Hương Xuân
6 năm trước

Được sửa đổi từ Mr ChuckBevitt

Giải pháp làm việc:

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);
}
Hữu ích 3 Chia sẻ Viết bình luận 1
Không hữu ích

Vì vậy, điều này giải quyết một vấn đề bộ nhớ phải không? Đây là từng dòng xử lý và không tồn tại trong bộ nhớ nên không có ngoại lệ? Tôi thích cách xử lý nhưng không File.ReadAllLines () lưu tất cả vào bộ nhớ? Tôi nghĩ bạn nên sử dụng File.ReadLines () để tránh bộ nhớ lớn? Đây là một câu trả lời tốt cho câu hỏi trong tay tôi chỉ muốn biết về mối quan tâm bộ nhớ.

Hữu ích 0 · Không hữu ích · Trả lời 0

2
Tạ Thục Tâm
10 năm trước

Đây là một giải pháp sử dụng trình điều khiển văn bản ODBC của ADO.Net:

Dim csvFileFolder As String = "C:\YourFileFolder"
Dim csvFileName As String = "YourFile.csv"

'Note that the folder is specified in the connection string,
'not the file. That's specified in the SELECT query, later.
Dim connString As String = "Driver={Microsoft Text Driver (*.txt; *.csv)};Dbq=" _
    & csvFileFolder & ";Extended Properties=""Text;HDR=No;FMT=Delimited"""
Dim conn As New Odbc.OdbcConnection(connString)

'Open a data adapter, specifying the file name to load
Dim da As New Odbc.OdbcDataAdapter("SELECT * FROM [" & csvFileName & "]", conn)
'Then fill a data table, which can be bound to a grid
Dim dt As New DataTableda.Fill(dt)

grdCSVData.DataSource = dt

Sau khi điền, bạn có thể định giá các thuộc tính của dữ liệu, như Cột Tên, để sử dụng tất cả các quyền hạn của các đối tượng dữ liệu ADO.Net.

Trong VS2008 bạn có thể sử dụng Linq để đạt được hiệu quả tương tự.

LƯU Ý: Đây có thể là một bản sao của câu hỏi SO này .

Hữu ích 2 Chia sẻ Viết bình luận 0
Không hữu ích

2
Võ Hải Nam
9 năm trước
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;
    }
}
Hữu ích 2 Chia sẻ Viết bình luận 0
Không hữu ích

2
Đỗ Xuân Vân
5 năm trước

Không thể cưỡng lại việc thêm spin của riêng tôi vào đây. Điều này tốt hơn và nhỏ gọn hơn nhiều so với những gì tôi đã sử dụng trong quá khứ.

Giải pháp này:

  • Không phụ thuộc vào trình điều khiển cơ sở dữ liệu hoặc thư viện bên thứ 3.
  • Sẽ không thất bại với tên cột trùng lặp
  • Xử lý dấu phẩy trong dữ liệu
  • Xử lý bất kỳ dấu phân cách nào, không chỉ dấu phẩy (mặc dù đó là mặc định)

Đây là những gì tôi nghĩ ra:

  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

Nó phụ thuộc vào một phương thức mở rộng ( Unique) để xử lý các tên cột trùng lặp được tìm thấy như câu trả lời của tôi trong Cách nối các số duy nhất vào danh sách các chuỗi

Và đây là BlankToNothingchức năng của trình trợ giúp:

  Public Function BlankToNothing(ByVal Value As String) As Object 
    If String.IsNullOrEmpty(Value) Then Return Nothing
    Return Value
  End Function
Hữu ích 2 Chia sẻ Viết bình luận 0
Không hữu ích

2
Hồ Hùng Thịnh
1 năm trước

Với Cinchoo ETL - một thư viện mã nguồn mở, bạn có thể dễ dàng chuyển đổi tệp CSV thành DataTable với một vài dòng mã.

using (var p = new ChoCSVReader(** YOUR CSV FILE **)
     .WithFirstLineHeader()
    )
{
    var dt = p.AsDataTable();
}

Để biết thêm thông tin, vui lòng truy cập bài viết codeproject.

Hy vọng nó giúp.

Hữu ích 2 Chia sẻ Viết bình luận 0
Không hữu ích

0
Phan Hồng Thịnh
1 năm trước

Sử dụng chức năng này, một chức năng giải quyết tất cả các vấn đề về dấu phẩy và trích dẫn:

public static DataTable CsvToDataTable(string strFilePath)
    {

        if (File.Exists(strFilePath))
        {

            string[] Lines;
            string CSVFilePathName = strFilePath;

            Lines = File.ReadAllLines(CSVFilePathName);
            while (Lines[0].EndsWith(","))
            {
                Lines[0] = Lines[0].Remove(Lines[0].Length - 1);
            }
            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; i++)
                dt.Columns.Add(Fields[i], typeof(string));
            DataRow Row;
            int rowcount = 0;
            try
            {
                string[] ToBeContinued = new string[]{};
                bool lineToBeContinued = false;
                for (int i = 1; i < Lines.GetLength(0); i++)
                {
                    if (!Lines[i].Equals(""))
                    {
                        Fields = Lines[i].Split(new char[] { ',' });
                        string temp0 = string.Join("", Fields).Replace("\"\"", "");
                        int quaotCount0 = temp0.Count(c => c == '"');
                        if (Fields.GetLength(0) < Cols || lineToBeContinued || quaotCount0 % 2 != 0)
                        {
                            if (ToBeContinued.GetLength(0) > 0)
                            {
                                ToBeContinued[ToBeContinued.Length - 1] += "\n" + Fields[0];
                                Fields = Fields.Skip(1).ToArray();
                            }
                            string[] newArray = new string[ToBeContinued.Length + Fields.Length];
                            Array.Copy(ToBeContinued, newArray, ToBeContinued.Length);
                            Array.Copy(Fields, 0, newArray, ToBeContinued.Length, Fields.Length);
                            ToBeContinued = newArray;
                            string temp = string.Join("", ToBeContinued).Replace("\"\"", "");
                            int quaotCount = temp.Count(c => c == '"');
                            if (ToBeContinued.GetLength(0) >= Cols && quaotCount % 2 == 0 )
                            {
                                Fields = ToBeContinued;
                                ToBeContinued = new string[] { };
                                lineToBeContinued = false;
                            }
                            else
                            {
                                lineToBeContinued = true;
                                continue;
                            }
                        }

                        //modified by Teemo @2016 09 13
                        //handle ',' and '"'
                        //Deserialize CSV following Excel's rule:
                        // 1: If there is commas in a field, quote the field.
                        // 2: Two consecutive quotes indicate a user's quote.

                        List<int> singleLeftquota = new List<int>();
                        List<int> singleRightquota = new List<int>();

                        //combine fileds if number of commas match
                        if (Fields.GetLength(0) > Cols) 
                        {
                            bool lastSingleQuoteIsLeft = true;
                            for (int j = 0; j < Fields.GetLength(0); j++)
                            {
                                bool leftOddquota = false;
                                bool rightOddquota = false;
                                if (Fields[j].StartsWith("\"")) 
                                {
                                    int numberOfConsecutiveQuotes = 0;
                                    foreach (char c in Fields[j]) //start with how many "
                                    {
                                        if (c == '"')
                                        {
                                            numberOfConsecutiveQuotes++;
                                        }
                                        else
                                        {
                                            break;
                                        }
                                    }
                                    if (numberOfConsecutiveQuotes % 2 == 1)//start with odd number of quotes indicate system quote
                                    {
                                        leftOddquota = true;
                                    }
                                }

                                if (Fields[j].EndsWith("\""))
                                {
                                    int numberOfConsecutiveQuotes = 0;
                                    for (int jj = Fields[j].Length - 1; jj >= 0; jj--)
                                    {
                                        if (Fields[j].Substring(jj,1) == "\"") // end with how many "
                                        {
                                            numberOfConsecutiveQuotes++;
                                        }
                                        else
                                        {
                                            break;
                                        }
                                    }

                                    if (numberOfConsecutiveQuotes % 2 == 1)//end with odd number of quotes indicate system quote
                                    {
                                        rightOddquota = true;
                                    }
                                }
                                if (leftOddquota && !rightOddquota)
                                {
                                    singleLeftquota.Add(j);
                                    lastSingleQuoteIsLeft = true;
                                }
                                else if (!leftOddquota && rightOddquota)
                                {
                                    singleRightquota.Add(j);
                                    lastSingleQuoteIsLeft = false;
                                }
                                else if (Fields[j] == "\"") //only one quota in a field
                                {
                                    if (lastSingleQuoteIsLeft)
                                    {
                                        singleRightquota.Add(j);
                                    }
                                    else
                                    {
                                        singleLeftquota.Add(j);
                                    }
                                }
                            }
                            if (singleLeftquota.Count == singleRightquota.Count)
                            {
                                int insideCommas = 0;
                                for (int indexN = 0; indexN < singleLeftquota.Count; indexN++)
                                {
                                    insideCommas += singleRightquota[indexN] - singleLeftquota[indexN];
                                }
                                if (Fields.GetLength(0) - Cols >= insideCommas) //probabaly matched
                                {
                                    int validFildsCount = insideCommas + Cols; //(Fields.GetLength(0) - insideCommas) may be exceed the Cols
                                    String[] temp = new String[validFildsCount];
                                    int totalOffSet = 0;
                                    for (int iii = 0; iii < validFildsCount - totalOffSet; iii++)
                                    {
                                        bool combine = false;
                                        int storedIndex = 0;
                                        for (int iInLeft = 0; iInLeft < singleLeftquota.Count; iInLeft++)
                                        {
                                            if (iii + totalOffSet == singleLeftquota[iInLeft])
                                            {
                                                combine = true;
                                                storedIndex = iInLeft;
                                                break;
                                            }
                                        }
                                        if (combine)
                                        {
                                            int offset = singleRightquota[storedIndex] - singleLeftquota[storedIndex];
                                            for (int combineI = 0; combineI <= offset; combineI++)
                                            {
                                                temp[iii] += Fields[iii + totalOffSet + combineI] + ",";
                                            }
                                            temp[iii] = temp[iii].Remove(temp[iii].Length - 1, 1);
                                            totalOffSet += offset;
                                        }
                                        else
                                        {
                                            temp[iii] = Fields[iii + totalOffSet];
                                        }
                                    }
                                    Fields = temp;
                                }
                            }
                        }
                        Row = dt.NewRow();
                        for (int f = 0; f < Cols; f++)
                        {
                            Fields[f] = Fields[f].Replace("\"\"", "\""); //Two consecutive quotes indicate a user's quote
                            if (Fields[f].StartsWith("\""))
                            {
                                if (Fields[f].EndsWith("\""))
                                {
                                    Fields[f] = Fields[f].Remove(0, 1);
                                    if (Fields[f].Length > 0)
                                    {
                                        Fields[f] = Fields[f].Remove(Fields[f].Length - 1, 1);
                                    }
                                }
                            }
                            Row[f] = Fields[f];
                        }
                        dt.Rows.Add(Row);
                        rowcount++;
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception( "row: " + (rowcount+2) + ", " + ex.Message);
            }
            //OleDbConnection connection = new OleDbConnection(string.Format(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0}; Extended Properties=""text;HDR=Yes;FMT=Delimited"";", FilePath + FileName));
            //OleDbCommand command = new OleDbCommand("SELECT * FROM " + FileName, connection);
            //OleDbDataAdapter adapter = new OleDbDataAdapter(command);
            //DataTable dt = new DataTable();
            //adapter.Fill(dt);
            //adapter.Dispose();
            return dt;
        }
        else
            return null;

        //OleDbConnection connection = new OleDbConnection(string.Format(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0}; Extended Properties=""text;HDR=Yes;FMT=Delimited"";", strFilePath));
        //OleDbCommand command = new OleDbCommand("SELECT * FROM " + strFileName, connection);
        //OleDbDataAdapter adapter = new OleDbDataAdapter(command);
        //DataTable dt = new DataTable();
        //adapter.Fill(dt);
        //return dt;
    }
Hữu ích 0 Chia sẻ Viết bình luận 2
Không hữu ích

ehhhhhhhhh ......

Hữu ích 0 · Không hữu ích · Trả lời 0

có tuyệt không bạn đã thử chưa

Hữu ích 0 · Không hữu ích · Trả lời 0

0
Đỗ Quang Nhân
1 năm trước

Chỉ cần chia sẻ phương pháp mở rộng này, tôi hy vọng rằng nó có thể giúp được ai đó.

public static List<string> ToCSV(this DataSet ds, char separator = '|')
{
    List<string> lResult = new List<string>();

    foreach (DataTable dt in ds.Tables)
    {
        StringBuilder sb = new StringBuilder();
        IEnumerable<string> columnNames = dt.Columns.Cast<DataColumn>().
                                          Select(column => column.ColumnName);
        sb.AppendLine(string.Join(separator.ToString(), columnNames));

        foreach (DataRow row in dt.Rows)
        {
            IEnumerable<string> fields = row.ItemArray.Select(field =>
              string.Concat("\"", field.ToString().Replace("\"", "\"\""), "\""));
            sb.AppendLine(string.Join(separator.ToString(), fields));
        }

        lResult.Add(sb.ToString());
    }
    return lResult;
}

public static DataSet CSVtoDataSet(this List<string> collectionCSV, char separator = '|')
{
    var ds = new DataSet();

    foreach (var csv in collectionCSV)
    {
        var dt = new DataTable();

        var readHeader = false;
        foreach (var line in csv.Split(new[] { Environment.NewLine }, StringSplitOptions.None))
        {
            if (!readHeader)
            {
                foreach (var c in line.Split(separator))
                    dt.Columns.Add(c);
            }
            else
            {
                dt.Rows.Add(line.Split(separator));
            }
        }

        ds.Tables.Add(dt);
    }

    return ds;
}
Hữu ích 0 Chia sẻ Viết bình luận 0
Không hữu ích

0
Trần Huy Lĩnh
1 năm trước
 Public Function ReadCsvFileToDataTable(strFilePath As String) As DataTable
    Dim dtCsv As DataTable = New DataTable()
    Dim Fulltext As String
    Using sr As StreamReader = New StreamReader(strFilePath)
        While Not sr.EndOfStream
            Fulltext = sr.ReadToEnd().ToString()
            Dim rows As String() = Fulltext.Split(vbLf)
            For i As Integer = 0 To rows.Count() - 1 - 1
                Dim rowValues As String() = rows(i).Split(","c)
                If True Then
                    If i = 0 Then
                        For j As Integer = 0 To rowValues.Count() - 1
                            dtCsv.Columns.Add(rowValues(j))
                        Next
                    Else
                        Dim dr As DataRow = dtCsv.NewRow()
                        For k As Integer = 0 To rowValues.Count() - 1
                            dr(k) = rowValues(k).ToString()
                        Next
                        dtCsv.Rows.Add(dr)
                    End If
                End If
            Next
        End While
    End Using
    Return dtCsv
End Function
Hữu ích 0 Chia sẻ Viết bình luận 0
Không hữu ích

Trả lời của bạn

Xem trước nội dung