Scala:自动检测CSV文件中的分隔符/分隔符
我正在使用OpenCSV库分割我的CSV文件。现在我需要绝对确定地检测分隔符/分隔符。 我在网上搜索过,但我只找到了一些例子,你可以创建一个候选名单,然后尝试其中一个。我认为这不是最好的方法,因为你很可能会出错。 我的拆分器应该在任何CSV(我没有控制权)上正常工作,因此它必须尽可能通用。Scala:自动检测CSV文件中的分隔符/分隔符,scala,csv,split,separator,opencsv,Scala,Csv,Split,Separator,Opencsv,我正在使用OpenCSV库分割我的CSV文件。现在我需要绝对确定地检测分隔符/分隔符。 我在网上搜索过,但我只找到了一些例子,你可以创建一个候选名单,然后尝试其中一个。我认为这不是最好的方法,因为你很可能会出错。 我的拆分器应该在任何CSV(我没有控制权)上正常工作,因此它必须尽可能通用。 有人有好的解决方案吗?您可能已经看到了这一点,它列出了一些好的策略,例如计算潜在分隔符出现的次数,和/或在使用假设的分隔符时验证每行的列数是否相同 不幸的是,绝对确定性是不可能的,因为该格式没有在文件中明确指
有人有好的解决方案吗?您可能已经看到了这一点,它列出了一些好的策略,例如计算潜在分隔符出现的次数,和/或在使用假设的分隔符时验证每行的列数是否相同 不幸的是,绝对确定性是不可能的,因为该格式没有在文件中明确指定分隔符的方法。我认为使其尽可能通用的最佳解决方案是让用户指定何时不是逗号(这是opencsv处理它的方式),或者如果您或他们确定自动检测失败,则允许客户端指定分隔符。如果这不能是交互式的,那么我认为你能做的最好的事情就是记录你认为失败的案例,以便他们以后处理 此外,我认为错误率将低于您的预期。我猜99%的时间分隔符是逗号、分号、句号或制表符。不幸的是,我看到懒惰的程序员在假设数据不包含字段的情况下,使用插入符号、管道或平铺来分隔字段,因此他们不必进行适当的转义。但这不是标准,也不应该被视为CSV
Python csv模块有一个猜测分隔符的类(用户提供候选项列表);您可能想看看它。我最近一直在处理CSV文件的分隔符/分隔符检测问题。我提出了以下建议,我希望这些建议能帮助其他人,或许还能收到反馈以改进 我的解决方案是基于我读过的关于这个问题的几篇文章。 因为对字段分隔符的定义没有限制,所以我决定使用ASCII表,除去明显的(字母数字字符)和不太明显的(不可打印的),但选项卡代码除外。使用这些值,我填充了一个字典,其中ASCII码是要用我的代码填充的值的键 然后是逐行阅读CSV,在每一行中查找字典中的关键字符,并增加我遇到的每一个字符的值。循环将继续到文件末尾,或者在本例中循环次数限制为100次。您可以根据需要进行更改,但100对于检测分隔符来说已经足够了。然后,定界符由具有最大值的字典键(ASCII码)确定 调用例程示例
private sub Main()
dim separator As Char
separator= separatorDetect(txtInputFile.Text)
end sub
主要检测功能
Private Function separatorDetect(ByVal StrFileName As String) As Char
Dim i As Int16 = 0
Dim separator As List(Of Char)
Dim dictSeparators As New Dictionary(Of Integer, Integer)
dictSeparators.Add(9, 0)
dictSeparators.Add(33, 0)
For i = 35 To 47
dictSeparators.Add(i, 0)
Next
For i = 91 To 96
dictSeparators.Add(i, 0)
Next
For i = 123 To 126
dictSeparators.Add(i, 0)
Next
Dim lineCounter As Integer = 0
Dim line As String = String.Empty
Dim keyList As New List(Of Integer)
For Each key In dictSeparators.Keys
keyList.Add(key)
Next
Dim tmp As Char
Using textReader = New StreamReader(StrFileName)
Do Until textReader.EndOfStream
line = textReader.ReadLine.Trim
For Each key In keyList
tmp = Convert.ToChar(key)
dictSeparators.Item(key) = dictSeparators.Item(key) + InStrCount(line, tmp)
Next
lineCounter += 1
If lineCounter = 99 Then GoTo readEnd
Loop
End Using
readEnd:
Dim max = dictSeparators.Aggregate(Function(l, r) If(l.Value > r.Value, l, r)).Key
Return Chr(max)
End Function
计数函数的递归索引
Private Function InStrCount(ByVal SourceString As String, ByVal SearchString As Char, _
Optional ByRef StartPos As Integer = 0, _
Optional ByRef Count As Integer = 0) As Integer
If SourceString.IndexOf(SearchString, StartPos) > -1 Then
Count += 1
InStrCount(SourceString, SearchString, SourceString.IndexOf(SearchString, StartPos) + 1, Count)
End If
Return Count
End Function
这对我来说很有效,但我总是很高兴能以一种更好、更优化的方式展示给大家。在中,我提到,这似乎是一个维护良好且受欢迎的库,它实际上提供了一个API来为您处理检测。有趣的是,CSV代表逗号分隔的值。@om nom nom如果总是这样的话,那就太好了。但现实是different@om-nom nom:有人说C代表性格。