c# - 从丢失小数位的 XML 中解析浮点值(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
通过将当前的 culure更改为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
类中的实用程序:
double startTimeValue = XmlConvert.ToDouble(startTime);
double endTimeValue = XmlConvert.ToDouble(endTime);
此类提供用于在公共语言运行时类型和 XML 架构定义语言 (XSD) 类型之间进行转换的方法。转换数据类型时,返回的值与语言环境无关。 因此,它封装了有关用于格式化原始类型的 XML 约定的详细信息。
演示小提琴 #2 在此处显示上述修复。
作为另一个更简单的选择,尝试使用LINQ to XML 解析您的 XML:
var doc = XDocument.Load(_projectFilePath);
var startTimeValue = (double)doc.Root.Attribute("start_datetime");
var endTimeValue = (double)doc.Root.Attribute("end_datetime");
LINQ to XMLXATtribute
支持直接转换为double
或decimal
消除对任何手动解析的需要。
演示小提琴#3在这里。
最后,在您的代码中,您执行以下操作:
double endTimeValue = double.Parse(startTime);
我认为这是您问题中的错字,应该改为:
double endTimeValue = double.Parse(endTime);
推荐阅读
- ag - FZF - 搜索目标文件夹
- sql-server - Visual Studio SSDT 数据库项目在重新启动时不会显示架构节点
- javascript - 在角度的标题excel js之前添加行
- python - 序列化 JSON 数据的问题
- mongodb - 如何在 mongodb 中更新文档而不删除其中包含的信息?
- node.js - 根据日期下载文件
- google-cloud-platform - Google Spanner Emulator - 任何查询都出现 HTTP 500 错误
- data-structures - 二叉树的最大深度是否应该排除根?
- python - 将 pandas 数据框作为 CSV 文件导出到 Azure Data Lake Storage?
- c# - 自动映射器使用返回“无法将'WebAPIs.Models.Store'类型的对象转换为'WebAPIs.ValueModels.StoreVM'”