[英]Parsing floating value from XML losing decimal places (C#)
我在 C#(在 Unity 内部,使用 VS2019)中有一个非常尴尬的行为,这让我疯狂了好几天,我真的很感谢你的帮助。
我有一个非常简单的 XML 文件,在这个简单的例子中只包含一个根节点和几个属性:
<?xml version="1.0" encoding="utf-8"?>
<root bit_depth="8" end_datetime="737061.75" start_datetime="737061">
</root>
我尝试阅读它:
XmlDocument document = new XmlDocument();
document.Load( _projectFilePath );
XmlElement root = document.DocumentElement;
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo( "en-US" );
string startTime = root.Attributes[ "start_datetime" ].Value;
Debug.Log( "1st::: Read startTime number: " + startTime );
double startTimeValue = double.Parse(startTime);
Debug.Log( "2nd::: Parse startTime number: " + startTimeValue );
string endTime = root.Attributes[ "end_datetime" ].Value;
Debug.Log( "1st::: Read endTime number: " + endTime );
double endTimeValue = double.Parse( endTime, CultureInfo.InvariantCulture );
Debug.Log( "2nd::: Parse endTime number: " + endTimeValue );
结果如下:
1st::: Read startTime number: 737061
2nd::: Parse startTime number: 737061
1st::: Read endTime number: 7,370618E+07
2nd::: Parse endTime number: 73706180000000
只是……为什么????,??! 当我显式解析双精度数时,为什么会将该浮点数弄乱为 7,370618E+07?
在您的问题中,文本中的双精度数使用逗号小数分隔符进行格式化: 7,370618E+07
。 这意味着您计算机上的 当前语言环境(由Thread.CurrentCulture
表示)使用此分隔符。
但是,XML 文件中的数字使用句点小数分隔符进行格式化: 737061.75
。 double.Parse()
将无法正确解析它们,因为使用为当前线程区域性初始化的NumberFormatInfo
object 中的格式信息解释输入字符串。 通过将当前的文化更改为new CultureInfo("de-DE")
,我能够在这里使用小提琴重现此问题。
由于 XML 文件通常使用不变的文化进行格式化,因此您应该使用不变的设置进行解析:
double startTimeValue = double.Parse(startTime, NumberFormatInfo.InvariantInfo);
double endTimeValue = double.Parse(endTime, NumberFormatInfo.InvariantInfo);
或者,使用System.Globalization.CultureInfo.InvariantCulture
:
double startTimeValue = double.Parse(startTime, System.Globalization.CultureInfo.InvariantCulture);
double endTimeValue = double.Parse(endTime, System.Globalization.CultureInfo.InvariantCulture);
最好使用XmlConvert
class 中的实用程序:
double startTimeValue = XmlConvert.ToDouble(startTime);
double endTimeValue = XmlConvert.ToDouble(endTime);
此 class提供了在公共语言运行时类型和 XML 架构定义语言 (XSD) 类型之间进行转换的方法。 转换数据类型时,返回的值与语言环境无关。 因此,它封装了有关用于格式化原始类型的 XML 约定的详细信息。
演示小提琴 #2 在此处显示上述修复。
作为另一个更简单的选择,尝试使用 LINQ 解析您的XML 到 XML :
var doc = XDocument.Load(_projectFilePath);
var startTimeValue = (double)doc.Root.Attribute("start_datetime");
var endTimeValue = (double)doc.Root.Attribute("end_datetime");
LINQ 到 XML 的XATtribute
支持直接转换为double
精度或decimal
,无需任何手动解析。
演示小提琴#3在这里。
最后,在您的代码中,您执行以下操作:
double endTimeValue = double.Parse(startTime);
我认为这是您问题中的错字,应该改为:
double endTimeValue = double.Parse(endTime);
我在 Visual Studio 和 dotnetfiddle 中运行了您的代码,得到了以下结果。
XmlDocument document = new XmlDocument();
document.LoadXml("<root bit_depth=\"8\" end_datetime=\"737061.75\" start_datetime=\"737061\"></root >");
string startTime = document.ChildNodes[0].Attributes["start_datetime"].Value;
Console.WriteLine("1st::: Read startTime number: " + startTime);
double startTimeValue = double.Parse(startTime);
Console.WriteLine("2nd::: Parse startTime number: " + startTimeValue);
string endTime = document.ChildNodes[0].Attributes["end_datetime"].Value;
Console.WriteLine("1st::: Read endTime number: " + endTime);
double endTimeValue = double.Parse(startTime);
Console.WriteLine("2nd::: Parse endTime number: " + endTimeValue);
1st::: Read startTime number: 737061
2nd::: Parse startTime number: 737061
1st::: Read endTime number: 737061.75
2nd::: Parse endTime number: 737061
我建议您检查文件的编码并使用相同的编码读取它。 并检查计算机上安装的本地化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.