检测 VB.Net 中数字的文化,即小数点/千位分隔符的句点或逗号
Posted
技术标签:
【中文标题】检测 VB.Net 中数字的文化,即小数点/千位分隔符的句点或逗号【英文标题】:Detect culture of number in VB.Net i.e. period or comma for decimal point / thousands separator 【发布时间】:2011-09-26 21:13:26 【问题描述】:在 VB.Net 中,有没有一种方法可以自动检测数字字符串表示的文化?我来解释一下情况:
我们的 asp.net 网站接收船数据的 xml 数据馈送。大多数时候,价格的数字格式使用简单的非格式化整数,例如“999000”。这对我们来说很容易处理。
有时,千位分隔符使用逗号,小数点使用句点。此外,这很好,因为我们的数据导入理解这一点。示例“999,000.00”。
我们开始从法国获取一些数据,其中一些价格已经输入了句点和千位分隔符,因为许多欧洲国家都是这样做的。例如。 “999.000,00”。在这里,我们的系统会将其解释为 999 磅,而不是预期的 999000 磅。
很遗憾,数据馈送包含多种格式的价格,每种格式都没有任何文化指标。有谁知道任何内置的 .net 函数可以根据句点和逗号的位置自动检测字符串数字的文化?
【问题讨论】:
想想你在问什么,你会意识到答案是“不,当然不是”。相反,也许您应该将您的提要定义为仅接受整数。事实上,价格的货币单位是什么?欧元?也许其中一些数字是法郎? 我同意最好的方法是更清楚地定义提要格式。我们正在开发一个新版本——但在完成之前,我们一直在努力充分利用这一版本。货币单位在 Feed 的单独字段中定义。 那么也许货币可以告知您对价格格式的看法? 对此有任何公认的答案吗?如果你能接受其中一个和/或评论它会很好,所以我们都可以跟随你的脚步。 TIMINeutron,是的,我很抱歉直到现在才回到这里。谢谢大家的回复。我认为最终 John Saunders 给出了答案——我们只需要继续修复提要格式并做好记录,以便清楚应该使用哪种格式。 【参考方案1】:我在 vbforums 上找到了a thread,建议如何按文化获取小数点分隔符。
我制作了一个转换器,可以使用 oledb、excel 对象、mysql 等在不同文件之间进行转换。当我转换为 Excel 和 Access 文件时,使用“decimalSeparator”是让数字格式正常工作的解决方案。
Dim decimalSeparator As String = Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator
cellValue = cellValue.Replace(".", decimalSeparator ).Replace(",", decimalSeparator )
【讨论】:
这确实是解决这个问题的方法。简单、准确且不基于用户输入。【参考方案2】:据我所知,没有内置方法可以从数字字符串中确定 CultureInfo。而且我严重怀疑它永远不会发生,因为没有 100% 安全的方法来做到这一点。
在您找到更好的解决方案之前(例如:在发送方进行一些更改),我想您能做的最好的事情就是分两步减少出错的机会:
1)输入数据的清理和标准化:
Dim input as String = " 99 9.000,00 "
' This way you can remove unwanted characters (anything that is not a digit, and the following symbols: ".", "-", ",")
Dim fixedInput as String = Regex.Replace(input, "[^\d-,\.]", "")
' fixedInput now is "999.000,00"
2) 自己猜格式:
Dim indexOfDot as Integer = fixedInput.IndexOf(".")
Dim indexOfComma as Integer = fixedInput.IndexOf(",")
Dim cultureTestOrder as List(Of CultureInfo) = new List(Of CultureInfo)
Dim parsingResult as Double?
Try
If indexOfDot > 0 And indexOfComma > 0 Then
' There are both the dot and the comma..let's check their order
If indexOfDot > indexOfComma Then
' The dot comes after the comma. It should be en-US like Culture
parsingResult = Double.Parse(fixedInput, NumberStyles.Number, CultureInfo.GetCultureInfo("en-US"))
Else
' The dot comes after the comma. It should be it-IT like Culture
parsingResult = Double.Parse(fixedInput, NumberStyles.Number, CultureInfo.GetCultureInfo("it-IT"))
End If
Else If indexOfDot = fixedInput.Length-3 Then
' There is only the dot! And it is followed by exactly two digits..it should be en-US like Culture
parsingResult = Double.Parse(fixedInput, NumberStyles.Number, CultureInfo.GetCultureInfo("en-US"))
Else If indexOfComma = fixedInput.Length-3 Then
' There is only the comma! And it is followed by exactly two digits..it should be en-US like Culture
parsingResult = Double.Parse(fixedInput, NumberStyles.Number, CultureInfo.GetCultureInfo("it-IT"))
End If
Catch
End Try
If Not parsingResult.HasValue Then
Try
' There is no dot or comma, or the parsing failed for some reason. Let's try a less specific parsing.
parsingResult = Double.Parse(fixedInput, NumberStyles.Any, NumberFormatInfo.InvariantInfo)
Catch
End Try
End If
If Not parsingResult.HasValue Then
' Conversion not possible, throw exception or do something else
Else
' Use parsingResult.Value
End If
这种方式不是 100% 安全的,但它应该仍然比您当前的代码更好(并且至少在您提供的示例数据上按预期工作)。
【讨论】:
谢谢 Fulvio - 我会试试这个和 debasnett 的方法。【参考方案3】:不知道字符串可以格式化多少种不同方式的细节...这适用于您提供的三个示例
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim v As String = "999.123,45"
Debug.WriteLine(foo(v))
v = "999,123.45"
Debug.WriteLine(foo(v))
v = "999123"
Debug.WriteLine(foo(v))
End Sub
Private Function foo(value As String) As Double
Dim style As NumberStyles = NumberStyles.AllowThousands Or NumberStyles.AllowDecimalPoint
Dim culture As CultureInfo = CultureInfo.InvariantCulture
Dim rv As Double
If Double.TryParse(value, style, culture, rv) Then
Debug.WriteLine(",.Converted '0' to 1.", value, rv)
Else
Dim styleES As NumberStyles = NumberStyles.AllowThousands Or NumberStyles.AllowDecimalPoint
Dim cultureES As CultureInfo = CultureInfo.CreateSpecificCulture("es-ES")
If Double.TryParse(value, styleES, cultureES, rv) Then
Debug.WriteLine(".,Converted '0' to 1.", value, rv)
Else
Throw New ArgumentException
End If
End If
Return rv
End Function
【讨论】:
谢谢 - 我会试试看。【参考方案4】:'这个变量在 OS 的情况下为 True。区域设置使用点作为小数分隔符,其他情况下为 false。
Dim bAmerican as boolean=Cdec("0,2") > 1
原帖: https://www.linkedin.com/groups/8141257/8141257-6347113651027079171
【讨论】:
以上是关于检测 VB.Net 中数字的文化,即小数点/千位分隔符的句点或逗号的主要内容,如果未能解决你的问题,请参考以下文章