添加一种方法将CSV中的逗号保存到DataTable函数

时间:2010-05-17 20:03:39

标签: c# asp.net vb.net

我有一个将.csv文件转换为数据表的函数。我正在转换的列之一是名称中包含逗号的字段,即转换函数时“Doe,John”因为逗号而将其视为2个单独的字段。我需要数据表来保存它作为数据表中的一个字段Doe,John。

Function CSV2DataTable(ByVal filename As String, ByVal sepChar As String) As DataTable
    Dim reader As System.IO.StreamReader
    Dim table As New DataTable
    Dim colAdded As Boolean = False

    Try
        ''# open a reader for the input file, and read line by line
        reader = New System.IO.StreamReader(filename)
        Do While reader.Peek() >= 0
            ''# read a line and split it into tokens, divided by the specified 
            ''# separators
            Dim tokens As String() = System.Text.RegularExpressions.Regex.Split _
                (reader.ReadLine(), sepChar)
            ''# add the columns if this is the first line
            If Not colAdded Then
                For Each token As String In tokens
                    table.Columns.Add(token)
                Next
                colAdded = True
            Else
                ''# create a new empty row
                Dim row As DataRow = table.NewRow()
                ''# fill the new row with the token extracted from the current 
                ''# line
                For i As Integer = 0 To table.Columns.Count - 1
                    row(i) = tokens(i)
                Next
                ''# add the row to the DataTable
                table.Rows.Add(row)
            End If
        Loop

        Return table
    Finally
        If Not reader Is Nothing Then reader.Close()
    End Try
End Function

6 个答案:

答案 0 :(得分:3)

您考虑使用

而不是推出自己的解决方案

http://www.filehelpers.net/

它应该解决你的问题。

答案 1 :(得分:3)

不要使用.Split()函数来读取csv数据。它不仅会导致您遇到的那种错误,而且速度也会变慢。您需要一个基于状态机的解析器。这样会更快,并且更容易正确处理引号括起的文本。

我在这里有一个例子:
Reading CSV files in C#

并且您可以在codeplex上使用备受推崇的CSV阅读器:
http://www.codeproject.com/KB/database/CsvReader.aspx


您可以使用我的代码:

Function DataTableFromCSV(ByVal filename As String) As DataTable
    Dim table As New DataTable
    Dim colAdded As Boolean = False

    For Each record As IList(Of String) In CSV.FromFile(filename)
        ''# Add column headers on first iteration
        If Not colAdded Then
            For Each token As String In record
                table.Columns.Add(token)
            Next token
            colAdded = True
        Else
            ''# add the row to the table
            Dim row As DataRow = table.NewRow()
            For i As Integer = 0 To table.Columns.Count - 1
                row(i) = record(i)
            Next
            table.Rows.Add(row)
        End If
    Next record

    Return table
End Function  

如果您正在使用.net 3.5或更高版本,我会稍微改写一下,将列创建从每个循环中拉出来(使用类型推断和.Take(1)),但我想成为确定这也适用于.Net 2.0。

答案 2 :(得分:1)

我无法帮助你解决VB.NET问题,但RFC 4180是你的朋友。具体而言,第2节:

  

5。每个字段可能包含也可能不包含在双引号中(但是          某些程序(如Microsoft Excel)不使用double   报价          在所有)。如果字段没有用双引号括起来,那么          双引号可能不会出现在字段内。例如:

   "aaa","bbb","ccc" CRLF
   zzz,yyy,xxx
     

6。包含换行符(CRLF),双引号和逗号的字段          应该用双引号括起来。例如:

   "aaa","b CRLF
   bb","ccc" CRLF
   zzz,yyy,xxx
     

7。如果使用双引号括起字段,则使用双引号          出现在一个字段内必须通过前面的方式进行转义          另一个双引号。例如:

   "aaa","b""bb","ccc"

答案 3 :(得分:0)

尝试拆分“ 然后从第一个元素开始跳过每个第二个元素。 例如:

 "Test,Name","123 Street,","NY","12345" 
Dim tokens As String() =  = System.Text.RegularExpressions.Regex.Split _
            (reader.ReadLine(), """") 'Or send in " as the sepchar

你会得到

 {Length=9}
    (0): ""
    (1): "Test,Name"
    (2): ","
    (3): "123 Street,"
    (4): ","
    (5): "NY"
    (6): ","
    (7): "12345"
    (8): ""

因此,您只需要使用奇数编号的元素来检索数据。唯一需要注意的是,在数据文件中还有一个“

我仍然认为您应该使用外部库重新考虑

这是一篇解决它的文章。 http://www.secretgeek.net/csv_trouble.asp

答案 4 :(得分:0)

像其他人所说的那样,不要自己动手。

尝试CSVHelper(我维护的库)。它分为解析器和读取器,因此您可以根据需要使用解析器。如果你想查看它的来源,解析代码非常简单且符合RFC 4180

答案 5 :(得分:0)

您是否考虑过使用内置于.Net框架中的TextFieldParser类?

它有一个名为HasFieldsEnclosedInQuotes的属性,可以处理你的情况。

您可以设置分隔符,然后调用ReadLine和ReadFields方法来获取字段数据,它应该考虑用引号括起来的那些字段。