如何独立于区域设置从 XML 文件中正确读取浮点值?
How to read a floating point value correctly from an XML file independently from regional settings?
我正在从 XML 文件中的一个节点读取浮点属性值 TXMLDocument
:
<MyApp_Favorites version="1.0">
...用这个语句:
var
ThisRootNode: IXMLNode;
ThisVersion: Single;
// ...
ThisVersion := ThisRootNode.Attributes['version'];
CodeSite.Send('ThisVersion', ThisVersion);
但是,在我的德语系统上,我得到这个版本值:
ThisVersion = 10,00
...在我的区域设置中,逗号“,”被定义为小数点分隔符,而不是点“.”与 XML 文件中一样。但是对于英语语言区域设置——点很可能被定义为小数点分隔符设置——结果将正确为“1.0”。
那么我如何确保独立于区域设置,1.0 的读取值始终相同? (将version值读成string再转成float好像不是很优雅的方法)
浮点数不是版本号的合理格式,舍入错误和缺乏可表示性是主要缺点。考虑使用带整数的记录来定义版本号。
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils, StrUtils, Types;
type
TVersion = record
private
procedure Set_AsString(AVersion : string);
function Get_AsString: String;
public
Major: Integer;
Minor: Integer;
property AsString: String read Get_AsString write Set_AsString;
end;
function TVersion.Get_AsString: String;
begin
Result := Format('%d.%d', [Major, Minor]);
end;
procedure TVersion.Set_AsString(AVersion: string);
var
split : TStringDynArray;
begin
split := SplitString(AVersion, '.');
Major := StrToInt(split[0]);
Minor := StrToInt(split[1]);
end;
var
v1, v2 : TVersion;
s : string;
begin
v1.Major := 12;
v1.Minor := 34;
WriteLn(v1.AsString);
s := v1.AsString;
v2.AsString := s;
WriteLn(v2.AsString);
ReadLn;
end.
不应将此值视为浮点值。您对二进制浮点类型的表示问题敞开心扉。更好的方法是读取字符串并解析出主要部分和次要部分,然后使用 StrToInt
将它们转换为整数。使用 Pos
拆分字符串本身以找到句点分隔符的位置,或者实际上使用任何 Split
函数。
另一方面,您甚至不清楚是否需要字符串以外的任何格式的此值。那么除了将其作为字符串读取之外,为什么还要费心做任何事情呢?
至于您提出的实际问题,您是否希望使用接受 TFormatSettings
参数的 StrToFloat
的重载。并传入将小数点分隔符设置为 '.'
.
的格式设置
使用字符串表示并使用 TFormatSettings.Invariant
:
自己进行转换
ThisVersion := StrToFloat(ThisRootNode.Attributes['version'], TFormatSettings.Invariant);
我正在从 XML 文件中的一个节点读取浮点属性值 TXMLDocument
:
<MyApp_Favorites version="1.0">
...用这个语句:
var
ThisRootNode: IXMLNode;
ThisVersion: Single;
// ...
ThisVersion := ThisRootNode.Attributes['version'];
CodeSite.Send('ThisVersion', ThisVersion);
但是,在我的德语系统上,我得到这个版本值:
ThisVersion = 10,00
...在我的区域设置中,逗号“,”被定义为小数点分隔符,而不是点“.”与 XML 文件中一样。但是对于英语语言区域设置——点很可能被定义为小数点分隔符设置——结果将正确为“1.0”。
那么我如何确保独立于区域设置,1.0 的读取值始终相同? (将version值读成string再转成float好像不是很优雅的方法)
浮点数不是版本号的合理格式,舍入错误和缺乏可表示性是主要缺点。考虑使用带整数的记录来定义版本号。
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils, StrUtils, Types;
type
TVersion = record
private
procedure Set_AsString(AVersion : string);
function Get_AsString: String;
public
Major: Integer;
Minor: Integer;
property AsString: String read Get_AsString write Set_AsString;
end;
function TVersion.Get_AsString: String;
begin
Result := Format('%d.%d', [Major, Minor]);
end;
procedure TVersion.Set_AsString(AVersion: string);
var
split : TStringDynArray;
begin
split := SplitString(AVersion, '.');
Major := StrToInt(split[0]);
Minor := StrToInt(split[1]);
end;
var
v1, v2 : TVersion;
s : string;
begin
v1.Major := 12;
v1.Minor := 34;
WriteLn(v1.AsString);
s := v1.AsString;
v2.AsString := s;
WriteLn(v2.AsString);
ReadLn;
end.
不应将此值视为浮点值。您对二进制浮点类型的表示问题敞开心扉。更好的方法是读取字符串并解析出主要部分和次要部分,然后使用 StrToInt
将它们转换为整数。使用 Pos
拆分字符串本身以找到句点分隔符的位置,或者实际上使用任何 Split
函数。
另一方面,您甚至不清楚是否需要字符串以外的任何格式的此值。那么除了将其作为字符串读取之外,为什么还要费心做任何事情呢?
至于您提出的实际问题,您是否希望使用接受 TFormatSettings
参数的 StrToFloat
的重载。并传入将小数点分隔符设置为 '.'
.
使用字符串表示并使用 TFormatSettings.Invariant
:
ThisVersion := StrToFloat(ThisRootNode.Attributes['version'], TFormatSettings.Invariant);