![]() |
inifile ReadFloat deutsch/english formatsettings
Würde gerne mit einem Deutschen Windows PC ( dezimale = 1,2 ) Ini files einlesen die jemand auf einem englischen PC geschrieben hat ( 1.2)
mit der Funktion Ini.ReadFloat(....) . Was muss ich machen damit ich beide Formate einlesen kann ?
Delphi-Quellcode:
fIni := TIniFile.Create(aFileName);
try X := fIni.ReadFloat(SectionStr, 'x', -99999); // mag nur Komma-Zahlen mit Deutschen Format 1,2 :-( finally fIni.free; end; |
AW: inifile ReadFloat deutsch/english formatsettings
Als String einlesen und mit StrToFloat umwandeln. Dabei die FormatSettings nach Bedarf setzen.
|
AW: inifile ReadFloat deutsch/english formatsettings
gibt's ne Lösung bei der ich nix selber schreiben muss .... eigentlich doch ne Aufgabe der Klasse inifile ......
|
AW: inifile ReadFloat deutsch/english formatsettings
Erstmal ist es totaler Schwachsinn, dass INIs überhaupt lokalisiert gespeichert/gelesen werden.
(aber für INIs gibt es ja leider auch eigentlich keine globale einheitliche Konvention/Richtline/Norm/...) Und leider kam in den letzten 20 Jahren auch noch keiner auf die Idee eine FormatSettings-Variable in TCustomIniFile für Floats und DateTimes einzufügen. Fazit:
Aber vielleicht wird das Problem ja im nächsten Jahrtausend behoben sein. :stupid: ![]() |
AW: inifile ReadFloat deutsch/english formatsettings
Oder du machst es dir einmal als
Delphi-Quellcode:
und benutzt dann einfach die folgende Unit in deiner
class helper
Delphi-Quellcode:
. Das ist das schwere Los eines Software-Entwicklers, manchmal muss man doch tatsächlich wenigstens noch ein
uses
Delphi-Quellcode:
tippen.
uses
Delphi-Quellcode:
unit System.IniFiles.TCustomIniFile.Helper;
interface uses System.IniFiles, System.SysUtils; type /// <summary> /// Ersetzt die Methode /// <c>WriteFloat</c> und deren <i>Read</i>-Gegenstück da die /// RTL-Implementation von <c>TCustomIniFile</c> dummerweise /// mit den <b>globalen Formatsettings</b> arbeitet /// </summary> /// <remarks> /// Floats werden mit <c>.</c> als <c>DecimalSeparator</c> geschrieben. /// </remarks> TCustomIniFileHelper = class helper for TCustomIniFile protected class var internalFormatSettings: TFormatSettings; protected class constructor Create(); public procedure WriteFloat(const Section, Name: string; Value: Double); function ReadFloat(const Section, Name: string; Default: Double): Double; end; implementation { TCustomIniFileHelper } class constructor TCustomIniFileHelper.Create(); begin internalFormatSettings := TFormatSettings.Invariant(); end; function TCustomIniFileHelper.ReadFloat( const Section, Name: string; Default: Double ): Double; var FloatStr: string; begin FloatStr := ReadString(Section, Name, ''); Result := Default; if FloatStr <> '' then try Result := StrToFloat(FloatStr, internalFormatSettings); except on EConvertError do Result := inherited ReadFloat(Section, Name, Default); else raise; end; end; procedure TCustomIniFileHelper.WriteFloat( const Section, Name: string; Value: Double ); begin WriteString(Section, Name, FloatToStr(Value, internalFormatSettings)); end; end. |
AW: inifile ReadFloat deutsch/english formatsettings
Zitat:
![]() |
AW: inifile ReadFloat deutsch/english formatsettings
Doppelpost
|
AW: inifile ReadFloat deutsch/english formatsettings
Eigentlich reicht es doch einfach das DecimalChar zu setzen:
Delphi-Quellcode:
var OrgDecSep: Char;
fIni := TIniFile.Create(aFileName); try try X := fIni.ReadFloat(SectionStr, 'x', -99999); // mag nur Komma-Zahlen mit Deutschen Format 1,2 :-( except OrgDecSep := FormatSettings.DecimalSeparator; try FormatSettings.DecimalSeparator := '.'; X := fIni.ReadFloat(SectionStr, 'x', -99999); // mag nur Komma-Zahlen mit Deutschen Format 1,2 :-( finally FormatSettings.DecimalSeparator := OrgDecSep; end; end; finally fIni.free; end; Oder wenn du genau weisst, dass das INI nach US/ANSI Regel gespeichert wurde, kannst du das auch einmalig vor der Verarbeitung der INI machen:
Delphi-Quellcode:
var OrgDecSep: Char;
OrgDecSep := FormatSettings.DecimalSeparator; fIni := TIniFile.Create(aFileName); try FormatSettings.DecimalSeparator := '.'; X := fIni.ReadFloat(SectionStr, 'x', -99999); // mag nur Komma-Zahlen mit Deutschen Format 1,2 :-( ... weitere ReadFLoat, etc. finally FormatSettings.DecimalSeparator := OrgDecSep; fIni.free; end; |
AW: inifile ReadFloat deutsch/english formatsettings
Zitat:
|
AW: inifile ReadFloat deutsch/english formatsettings
Es ist egal, ob DAS in einem Thread oder im Hauptthread abläuft ... wenn irgendwer Anderes in einem "anderen" Thread gleichzeitig das auch nutzen oder gar ebenfalls ändern will, dann ...
|
AW: inifile ReadFloat deutsch/english formatsettings
Da mich das auch immer genervt hat, habe ich vor Ewigkeiten die
![]() ![]() ![]() |
AW: inifile ReadFloat deutsch/english formatsettings
Ich habe meine Anwendung so umgestellt, dass der Speicher als Int64 interpretiert wird, wenn ich ein TDateTime speichern oder lesen möchte.
Delphi-Quellcode:
type TJanniINIFile = class helper for TIniFile
public constructor CreateForceFile(const FileName: string); // Erstellt gegebenenfalls den Ordner procedure WriteDouble(const Section, Ident: string; const Value: Double); // Mein Versuch, TDateTime regionsunabhängig zu schreiben function ReadDouble(const Section, Ident: string; const Default: Double): Double; end; { TJanniINIFile } constructor TJanniINIFile.CreateForceFile(const FileName: string); begin ForceDirectories(ExtractFilePath(Filename)); Create(FileName); end; function TJanniINIFile.ReadDouble(const Section, Ident: string; const Default: Double): Double; var Pointer: PDouble; Pointer2: PInt64; Int: Int64; begin Pointer2 := @Default; Int := StrToInt64Def(ReadString(Section, Ident, ''), Pointer2^); Pointer := @Int; Result := Pointer^; end; procedure TJanniINIFile.WriteDouble(const Section, Ident: string; const Value: Double); var Pointer: PInt64; begin Pointer := @Value; WriteString(Section, Ident, IntToStr(Pointer^)); end; |
AW: inifile ReadFloat deutsch/english formatsettings
Pointer sind bei uns - zum Glück - zu Recht - verboten.
Wenn es um Datum geht würde ich das in ANSI-Format speichern. Aber Fragenden ging es wohl um "normale" Double. Zitat:
|
AW: inifile ReadFloat deutsch/english formatsettings
Ja. XML kann über einen Header bestimmt werden, was für eine Codierung gilt. Ohne den Header ist es per Definition UTF-8. JSON ist nach meinem Wissenstand per Definition immer UTF-8.
|
AW: inifile ReadFloat deutsch/english formatsettings
Zitat:
|
AW: inifile ReadFloat deutsch/english formatsettings
Hier als Lösungsvorschlag eine Funktion ConvertStr um einen String in ein Double zu verwandeln
und dabei . und , alternativ zu akzeptieren sowie spaces zu ignorieren. Um INI Dateien zu lesen meiner Ansicht nach recht zweckmässig, um beim Start eines Programmes Exceptions zu vermeiden.
Code:
function ConvertStr( const str : string ) : Double;
var i : Integer; fNeg, fDez : Boolean; c : Char; fN, fDD : Double; begin fN := 0; fNeg := FALSE; fDez := FALSE; fDD := 10; for i := 1 to Length(str) do begin c := str[i]; if c = '-' then fNeg := not fNeg else if c = '.' then fDez := true else if c = ',' then fDez := true else if c in ['0'..'9'] then begin if fDez then begin fN := fN + (Integer(c) - Integer('0'))/fDD; fDD := fDD * 10; end else begin fN := fN * 10 + (Integer(c) - Integer('0')); end; end // Wenn auskommentiert werden unerwartete Zeichen einfach ignoriert // else break ; end; if fNeg then Result := -fN else Result := fN; end; |
AW: inifile ReadFloat deutsch/english formatsettings
XML nein, da sind Floats garnicht gefiniert (alles als String und das Format ist nicht vorgegeben)
aber JSON ja, denn dort ist ALLES ganz genau definiert, zumindestens bei Sting, Boolean, Integer und Float. (fast, denn beim Datum gibt es zwar indirekt eine Quasi-Vorgabe, aber Datum als "Typ" gibt es das per-se nicht) ![]() |
AW: inifile ReadFloat deutsch/english formatsettings
Zitat:
|
AW: inifile ReadFloat deutsch/english formatsettings
Und was sind die ANSI-Regeln für Zahlendarstellung?
Wen ich google nach "ansi Zahlendarstellung" komme ich z.B. auf ![]() |
AW: inifile ReadFloat deutsch/english formatsettings
IEEE754 ist für das interne Speicherformat innerhalb des Speichers.
Aber passend zu diesem Format gibt es. ![]() |
AW: inifile ReadFloat deutsch/english formatsettings
Zitat:
Zitat:
Es gibt halt keinen verlustfreien Weg, eigentlich inkompatiblen Speicher zu casten. |
AW: inifile ReadFloat deutsch/english formatsettings
Zitat:
DezimalSeparator = . ThousandSeparator = , Der ThousandSeparator würde ich aber beim Speichern der Zahl immer weglassen und nur den Punkt als Dezimalzeichen verwenden. Beim Einlsende der Daten muss einfach klar sein, wie diese Zahlen vorliegen und das dann entsprechend behandelt werden. Ich mache das immer nach mienem Beispiel, das ich gepostet habe. Thread spielen bei mir dabei keine Rolle, da ich sowas nicht in einem Thread nutze. Da müsste man das dann anders lösen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:35 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz