通过CSV查找具有特定标题的列

时间:2012-05-17 14:35:12

标签: c# csv filestream seek

我正在开发一个程序,您可以从csv文件中选择一个标题(它最初解析标题),我希望用户能够获取列的数据,而无需读取整个文件。一个字符串数组列表,并提取信息的字符串数组索引,这是很简单的事情。)

有没有办法可以使用seek来做到这一点?也许会搜索一个字符串(也就是标题)并在其列中获取信息。

这是getHeader函数,以防它有用......

private string[] getHeader(string path)//gets the headers from the file path specified.
    {          
        List<string> row = new List<string>();

        using (StreamReader readFile = new StreamReader(path))
        {          
            row = (readFile.ReadLine().Split(',').ToList());                
        }

        return row.ToArray();

    }

(列表和数组只是为了解决最初设置数组的大小...)

谢谢!

1 个答案:

答案 0 :(得分:2)

不可能。

Seek可以在文件中找到一个明确的位置。如果您有一个具有巨大记录长度和少量记录的固定长度记录(SDF / COBOL)文件,这将是一个好主意。

不幸的是,.csv的定义是可变长度记录。您只能根据记录末尾的cr / lf来判断一条记录的停止和开始位置。

即使使用大多数固定记录格式,这也不是一个好主意。由于缓冲,操作系统无论如何都会读取整个文件,因为您将提前获取较小的数量,然后操作系统已预先加载。

我明白你为什么要这样做;直观地说,它听起来会更快。虽然你应该始终考虑速度设计你的代码,但这个级别很低,足以被称为“过早优化” - 谷歌。基本上你必须通过编写它来证明它运行缓慢,然后,当你发现它是功能的一个巨大障碍时,你可以进行优化。

请勿自行解析!

MS对此有一个组合。 Microsoft.VisualBasic.FileIO.TextFieldParser。是的,您可以将它与C#一起使用(即使下面的示例是在VB中,您可以弄清楚您需要做什么)。不要太自豪地包含对VB的引用。你的口袋里的时间和金钱很重要,不能说,“我不会用10英尺的杆子接触VB。”更改是目标PC上的程序集已经完成。唯一需要关注的是,如果您有程序安装包下载大小问题,或者正在部署到非PC平台。

    Using Reader As New Microsoft.VisualBasic.FileIO.TextFieldParser(CSVPath)

        Reader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited
        Reader.Delimiters = New String() {","}
        Reader.TrimWhiteSpace = True
        Reader.HasFieldsEnclosedInQuotes = True

        While Not Reader.EndOfData
            Try
                Dim st2 As New List(Of String)
                st2.addrange(Reader.ReadFields())
                If iCount > 0 Then ' ignore first row = field names
                    Dim p As New clsPerson
                    p.CSVLine = st2
                    While p.CSVLine.Count < 15
                        p.CSVLine.Add("")
                    End While
                    p.FirstName = st2(1).Trim
                    If st2.Count > 2 Then
                        p.MiddleName = st2(2).Trim
                    Else
                        p.MiddleName = ""
                    End If
                    p.LastNameSuffix = st2(0).Trim
                    If st2.Count >= 6 Then
                        p.TestCase = st2(5).Trim
                    End If
                    If st2(3) > "" Then
                        p.CertsFromCase.Add(st2(3))
                    End If
                    cases.Add(p)
                Else
                    stFirstRow = CatLine(st2.ToArray)
                    Dim st3(6) As String
                    For kk As Integer = 0 To Math.Min(st2.Count - 1, 5)
                        st3(kk) = st2(kk)
                    Next
                    If 0 = InStr(st3(0), "Last Name", CompareMethod.Text) Or _
                     0 = InStr(st3(1), "First Name", CompareMethod.Text) Or _
                     0 = InStr(st3(2), "Middle Name", CompareMethod.Text) Or _
                     0 = InStr(st3(3), "Policy", CompareMethod.Text) Or _
                     0 = InStr(st3(5), "Test Case", CompareMethod.Text) Then
                        stFirstRow = "Last Name,First Name,Middle Name,Policy,,Test Case #" & vbCrLf & stFirstRow
                    End If
                End If
            Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
                MsgBox("Line " & ex.Message & " is not valid and will be skipped.")
            End Try
            iCount += 1
        End While
    End Using