5

我正在使用TextFieldParser该类来读取逗号分隔值 (.csv) 文件。此文件中的字段用双引号括起来,例如"Field1","Field2".

所以,为了读取文件,我将对象的HasFieldsEnclosedInQuotes属性设置TextFieldParser为 true。MalformedLineException但是当任何字段在开头包含双引号 (`"+ ) 时,我会收到错误消息。

示例:""Field2"with additional"在这里我应该看到"Field2" with additional输出。

但是,如果"在除第一个位置之外的任何位置,则它可以正常工作。就像 line with"Field2 "with" additional"工作得很好,并给了我Field2 "with" additional 作为输出。

有没有人有同样的问题?有什么办法可以解决这个问题吗?

这是我的代码:

Private Sub ReadTextFile(ByVal txtFilePath As String)
    Dim myReader As tfp = New Microsoft.VisualBasic.FileIO.TextFieldParser(txtFilePath)
    myReader.Delimiters = New String() {","}
    myReader.TextFieldType = FileIO.FieldType.Delimited
    myReader.HasFieldsEnclosedInQuotes = True
    myReader.TrimWhiteSpace = True
    Dim currentRow As String()
    Dim headerRow As Integer = 0

    While Not myReader.EndOfData
        Try
            currentRow = myReader.ReadFields()

            'Read Header
            If (headerRow = 0) Then
               'Do work for Header Row
                headerRow += 1
            Else
                'Do work for Data Row
            End If

        Catch ex As Exception
            Dim errorline As String = myReader.ErrorLine
        End Try
    End While

End Sub

这是我在 csv 文件中的数据:

“列 1”、“列 2”、“列 3”
"Value1","Value2",""A" 123 号楼"
4

2 回答 2

9

您的示例""A" Block"是格式错误的 CSV;因此,TextFieldParser 完全有权拒绝它。CSV 标准说:

7.  If double-quotes are used to enclose fields, then a double-quote
    appearing inside a field must be escaped by preceding it with
    another double quote.  For example:

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

如果您正确编码数据,即...

"Column1","Column2","Column3"
"Value1","Value2","""A"" Block in Building 123"

... TextFieldParser 工作正常并正确返回"A" Block in Building 123

因此,第一步是告诉生成 CSV 文件的人创建一个有效的 CSV 文件,而不是一些看起来像 CSV 但不是的东西。

如果你不能这样做,你可能想要通过文件进行两次传递:

  • 通过将文件转换为“有效”的 CSV 文件来修复文件(例如,用两个引号替换不带逗号或不带逗号的引号)。
  • 然后,TextFieldParser 可以毫无问题地解析“有效”的 CSV 文件。
于 2013-05-16T14:44:01.320 回答
-1

[原答案]

尝试这个:

using System;
using System.IO;
using System.Linq;

class Test
{
    static void Main()
    {
        var file = "Test.txt";

        var r = File.ReadAllLines(file)
            .Select((i, index) => new { Line = index, Fields = i.Split(new char[] { ',' }) });

        // header
        var header = r.First();

        // do work for header
        for (int j = 0; j < header.Fields.Count(); j++)
        {
            Console.Write("{0} ", header.Fields[j].Substring(1, header.Fields[j].Length-2));
        }
        Console.WriteLine();

        var rows = r.Skip(1).ToList();

        // do work for rows
        for (int i = 0; i < rows.Count; i++)
        {
            for (int j = 0; j < rows[i].Fields.Count(); j++)
            {
                Console.Write("{0} ", rows[i].Fields[j].Trim(new[] { '"' }));
            }
            Console.WriteLine();
        }
    }

}

注意:我在 C# 中发布,因为问题仍然被它标记。

由于 C# 标记已消失,请参阅http://converter.telerik.com/以获取将代码转换为 VB 的帮助。

[更新答案]

尝试不同的方法(这次是在 VB.Net 中):

Imports System
Imports System.IO
Imports System.Linq

Class Test
    Public Shared Sub Main()
        Dim file__1 = "Test.txt"

        Dim r = File.ReadAllLines(file__1).[Select](Function(i, index) New With { _
            .Line = index, _
            .Fields = i.Substring(1, i.Length - 2).Split(New String() {""","""}, StringSplitOptions.None) _
        })

        ' header
        Dim header = r.First()

        ' do work for header
        For j As Integer = 0 To header.Fields.Count() - 1
            Console.Write("{0} ", header.Fields(j))
        Next
        Console.WriteLine()

        Dim rows = r.Skip(1).ToList()

        ' do work for rows
        For i As Integer = 0 To rows.Count - 1
            For j As Integer = 0 To rows(i).Fields.Count() - 1
                Console.Write("{0} ", rows(i).Fields(j))
            Next
            Console.WriteLine()
        Next
    End Sub
End Class
于 2013-05-16T14:24:42.587 回答