我有一个将.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
答案 0 :(得分:3)
答案 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)
答案 5 :(得分:0)
您是否考虑过使用内置于.Net框架中的TextFieldParser类?
它有一个名为HasFieldsEnclosedInQuotes的属性,可以处理你的情况。
您可以设置分隔符,然后调用ReadLine和ReadFields方法来获取字段数据,它应该考虑用引号括起来的那些字段。