C# 添加在CSV To DataTable函数中保留逗号的方法

C# 添加在CSV To DataTable函数中保留逗号的方法,c#,asp.net,vb.net,C#,Asp.net,Vb.net,我有一个将.csv文件转换为数据表的函数。我正在转换的一列是一个名称字段,其中包含一个逗号,即“Doe,John”。由于逗号的存在,转换函数时将其视为两个单独的字段。我需要数据表将其保存为数据表中的一个字段Doe,John Function CSV2DataTable(ByVal filename As String, ByVal sepChar As String) As DataTable Dim reader As System.IO.StreamReader Dim ta

我有一个将.csv文件转换为数据表的函数。我正在转换的一列是一个名称字段,其中包含一个逗号,即“Doe,John”。由于逗号的存在,转换函数时将其视为两个单独的字段。我需要数据表将其保存为数据表中的一个字段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

您是否考虑过使用


它应该解决您的问题。

您是否考虑过使用

它应该能解决您的问题。

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

我这里有一个例子:

codeplex上还有一个备受尊敬的CSV阅读器,您可以使用:


您可以这样使用我的代码:

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  
如果您使用的是.NET3.5或更高版本,我会编写一些不同的代码,以将列创建从for-each循环中拉出(使用类型推断和
.Take(1)
),但我想确保这也适用于.NET2.0

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

我这里有一个例子:

codeplex上还有一个备受尊敬的CSV阅读器,您可以使用:


您可以这样使用我的代码:

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  
如果您使用的是.NET3.5或更高版本,我会编写一些不同的代码,以将列创建从for-each循环中拉出(使用类型推断和
.Take(1)
),但我想确保这也适用于.NET2.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): ""
因此,您只需要使用编号为奇数的元素来检索数据。唯一需要注意的是,数据文件中还有一个“字符”

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

这里有一篇文章论述了这一点。

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

 "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): ""
因此,您只需要使用编号为奇数的元素来检索数据。唯一需要注意的是,数据文件中还有一个“字符”

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

这里有一篇文章论述了这一点。

我在VB.NET方面帮不了你,但我是你的朋友。具体而言,第2节:

五,。每个字段可以用双引号括起来,也可以不用双引号括起来(但是 有些程序,如Microsoft Excel,不使用双精度 引用 完全没有)。如果字段没有用双引号括起来,则 双引号不能出现在字段内。例如:

 "Test,Name","123 Street,","NY","12345" 
Dim tokens As String() =  = System.Text.RegularExpressions.Regex.Split _
            (reader.ReadLine(), """") 'Or send in " as the sepchar
   "aaa","bbb","ccc" CRLF
   zzz,yyy,xxx
   "aaa","b CRLF
   bb","ccc" CRLF
   zzz,yyy,xxx
   "aaa","b""bb","ccc"
六,。包含换行符(CRLF)、双引号和逗号的字段 应该用双引号括起来。例如:

 "Test,Name","123 Street,","NY","12345" 
Dim tokens As String() =  = System.Text.RegularExpressions.Regex.Split _
            (reader.ReadLine(), """") 'Or send in " as the sepchar
   "aaa","bbb","ccc" CRLF
   zzz,yyy,xxx
   "aaa","b CRLF
   bb","ccc" CRLF
   zzz,yyy,xxx
   "aaa","b""bb","ccc"
七,。如果使用双引号括起字段,则使用双引号 出现在字段中时,必须在其前面加上 另一个双引号。例如:

 "Test,Name","123 Street,","NY","12345" 
Dim tokens As String() =  = System.Text.RegularExpressions.Regex.Split _
            (reader.ReadLine(), """") 'Or send in " as the sepchar
   "aaa","bbb","ccc" CRLF
   zzz,yyy,xxx
   "aaa","b CRLF
   bb","ccc" CRLF
   zzz,yyy,xxx
   "aaa","b""bb","ccc"

在VB.NET方面我帮不了你,但我是你的朋友。具体而言,第2节:

五,。每个字段可以用双引号括起来,也可以不用双引号括起来(但是 有些程序,如Microsoft Excel,不使用双精度 引用 完全没有)。如果字段没有用双引号括起来,则 双引号不能出现在字段内。例如:

 "Test,Name","123 Street,","NY","12345" 
Dim tokens As String() =  = System.Text.RegularExpressions.Regex.Split _
            (reader.ReadLine(), """") 'Or send in " as the sepchar
   "aaa","bbb","ccc" CRLF
   zzz,yyy,xxx
   "aaa","b CRLF
   bb","ccc" CRLF
   zzz,yyy,xxx
   "aaa","b""bb","ccc"
六,。包含换行符(CRLF)、双引号和逗号的字段 应该用双引号括起来。例如:

 "Test,Name","123 Street,","NY","12345" 
Dim tokens As String() =  = System.Text.RegularExpressions.Regex.Split _
            (reader.ReadLine(), """") 'Or send in " as the sepchar
   "aaa","bbb","ccc" CRLF
   zzz,yyy,xxx
   "aaa","b CRLF
   bb","ccc" CRLF
   zzz,yyy,xxx
   "aaa","b""bb","ccc"
七,。如果使用双引号括起字段,则使用双引号 出现在字段中时,必须在其前面加上 另一个双引号。例如:

 "Test,Name","123 Street,","NY","12345" 
Dim tokens As String() =  = System.Text.RegularExpressions.Regex.Split _
            (reader.ReadLine(), """") 'Or send in " as the sepchar
   "aaa","bbb","ccc" CRLF
   zzz,yyy,xxx
   "aaa","b CRLF
   bb","ccc" CRLF
   zzz,yyy,xxx
   "aaa","b""bb","ccc"

就像其他人说的,不要自己滚


试试(我维护的图书馆)。它分为解析器和读取器,因此如果需要,您可以直接使用解析器。如果您想查看解析代码的源代码,那么解析代码非常直截了当且符合要求。

正如其他人所说,不要使用自己的代码


试试(我维护的图书馆)。它分为解析器和读取器,因此如果需要,您可以直接使用解析器。如果您想查看解析代码的源代码,那么它是非常直接和兼容的。

您研究过使用内置在.Net framework中的类吗

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


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

您研究过使用内置在.Net framework中的类吗

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


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

如果您能提供帮助,我宁愿对我的字段进行更改。提前谢谢你。如果你能帮忙的话,我想换一下我的。提前谢谢。Joel没有简单的方法修复我的代码来解释这个问题。我不想从头开始,也不想使用任何开源dll。从技术上讲,可以重新编写正则表达式来解释引号内的文本。然而,这将不是一个简单的正则表达式。无论何时