如果逗号(,)在引号中,忽略CSV文件中的逗号(,)的最佳方法是什么?

时间:2012-10-01 15:37:44

标签: csv datatable

我有一个小程序来读取CSV文件以构建数据表。如果逗号在引号之间,则一个要求是忽略逗号(名称中的逗号等)。例。

          Name, Age, Location
          "Henderson, David", 32, London
           John Smith, 19, Belfast

程序应该忽略Henderson之后的逗号,并将Henderson,David视为一个字段。我当前的代码无法完成这项工作,最后添加额外的列。那么我该如何实现呢?解决方案不应该替换引号之间的逗号。感谢。

我目前的代码。

 Public Function BuildDataTable() As DataTable

    Dim myTable As DataTable = New DataTable("MyTable")
    Dim i As Integer
    Dim myRow As DataRow
    Dim fieldValues As String()        
    Dim myReader As StreamReader = New StreamReader(_fileFullPath, Encoding.GetEncoding("iso-8859-1"))

    Try           
        fieldValues = myReader.ReadLine().Split(_seperator)
        'Create data columns accordingly
        If _hasheader = False Then
            For i = 0 To fieldValues.Length() - 1
                myTable.Columns.Add(New DataColumn("Column(" & i & ")"))
            Next
        Else
            'if the file has header, take the first row as header for datatable
            For i = 0 To fieldValues.Length() - 1
                myTable.Columns.Add(New DataColumn(fieldValues(i).Replace(" ", "")))
            Next
        End If

        myRow = myTable.NewRow

        If _hasheader = False Then
            For i = 0 To fieldValues.Length() - 1
                myRow.Item(i) = fieldValues(i).ToString
            Next
            myTable.Rows.Add(myRow)
        End If

        While myReader.Peek() <> -1
            fieldValues = myReader.ReadLine().Split(_seperator)
            myRow = myTable.NewRow
            For i = 0 To fieldValues.Length() - 1
                myRow.Item(i) = fieldValues(i).Trim.ToString
            Next

            If Not csv2xml.AreAllColumnsEmpty(myRow) = True Then
                myTable.Rows.Add(myRow)
            End If

        End While
    Catch ex As Exception                   
    End Try     
End Function

2 个答案:

答案 0 :(得分:3)

您希望在CSV中使用双引号字符作为文本限定符。如果字段包含在文本限定符中,则文本限定符允许您在字段值中使用字段分隔符。

你可以自己编程,但这是一个错误。有很多免费且功能强大的CSV解析器可以为您完成此任务。由于您使用的是Visual Basic,因此可以查看TextFieldParser class

您仍然需要编写将CSV内容写入DataTable的代码。

我发现以下似乎有效:
http://www.vbcode.com/asp/showsn.asp?theID=13645

另一个选项是在GenericParsercodeproject.com结束。不要让文章中的代码用C#编写的事实打扰你;您仍然可以在项目中引用DLL(GenericParsing.dll)并在VB中使用它。

这个解析器的好处是它包含了一个可以用来从CSV返回DataTable的方法。以下是一个适用于您的示例数据的示例:

Using parser As New GenericParsing.GenericParserAdapter(CSV_FILE_FULLNAME)
    parser.ColumnDelimiter = ","
    parser.TextQualifier = """"
    parser.FirstRowHasHeader = True
    Dim dt As DataTable = parser.GetDataTable()
End Using

答案 1 :(得分:0)

我不熟悉Visual Basic,但我认为你不应该使用Split()函数来分割行。

fieldValues = myReader.ReadLine().Split(_seperator)    ' DO NOT do this

相反,编写自己的split函数,逐个读取每个字符。然后有一个标志来记录你是否在双引号之间。


<强>更新

对不起,我对VB或C#知之甚少,无法编写可运行的代码片段。 请阅读此伪代码(事实上它是JavaScript)...希望它有用。

function split_with_quote(string, delimiter, quotation) {
    if (delimiter == null) delimiter = ',';
    if (quotation == null) quotation = '"';
    var in_quotation = false;
    var result = [];
    var part = '';
    for (var i = 0; i < string.length; i++) {
        var ch = string[i];
        if (ch == quotation)  in_quotation = !in_quotation;
        if (ch == delimiter && !in_quotation) {
            result.push(part);
            part = '';
        } else {
            if (ch != quotation) part += ch;
        }
    }
    return result;
}

a = 'abc,def,"ghi,jkl",123';
split_with_quote(a);    // ["abc", "def", "ghi,jkl"]