Autor Beitrag
mats74
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 189
Erhaltene Danke: 26

Win 10
VS 2017/19, C++, C#
BeitragVerfasst: Mo 27.10.14 13:05 
Hallo zusammen

Nach einem Update von Windows 8 bekomme ich in einer TextBox, die ich aus der Datenbank beschreibe, bei einer Dezimalzahl ein Komma anstelle eines Punktes als Rückgabewert.
Dies entspricht nicht den Ländereinstellungen die auf dem Rechner als auch auf dem Server eingestellt sind.
Dort sind jeweils die Einstellungen auf Punkt gesetzt.

Dieser Umstand lässt natürlich die Methode Convert.toDouble() in eine Exception laufen, da ich keine Kultur mit dem entsprechenden Trennzeichen oder ein Replace(",", ".") an dieser Methode mitgegeben habe.

Diese Konvertierungen werden in der gesamten Programmumgebung ein Vielfaches angewendet.

Meine Frage:
Kann ich die Interpretation aus dem Betriebssystem beeinflussen ohne dass ich den Text zuerst konvertiere?
Muss ich jedem Konvertieren eine entsprechende Kultur mitgeben?
(In meiner Applikation so gegen 5000)

_________________
Gruss
mats74
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mo 27.10.14 14:13 
Zitat:
Muss ich jedem Konvertieren eine entsprechende Kultur mitgeben?


Das wäre absolut Best Practise insbesondere da du ja von mehreren beteiligten Rechnern ausgehst. Zum Datenaustausch (wenn der warum auch immer als string stattfindet) solltest du immer was systemunabhängiges nehmen. Da biete sich insbesondere die InvariantCulture an.

Zitat:
Muss ich jedem Konvertieren eine entsprechende Kultur mitgeben? (In meiner Applikation so gegen 5000)


Einmal entsprechend programmieren kapseln und dann da verwenden wo man es braucht. Einfachstes Programmierer Handwerk

Zitat:
Kann ich die Interpretation aus dem Betriebssystem beeinflussen ohne dass ich den Text zuerst konvertiere?


Die entsprechenden Ländereinstellungen pflegen für die Sprache in dem der aktuelle Thread auch tatsächlich läuft.
Du könntest zum Beispiel Thread.CurrentCulture auf eine Culture setzen die so funktioniert wie du es wünscht. Oder falls du nicht möchtest das du in Probleme läufst wenn auf einem der beteiligten Rechner jemand die Defaults dieser Culture in den Ländereinstellungen verstellt hat erzeug deine eigene Culture mit passenden Settings. Das wäre aber nur eine Notfall Lösung sauberer ist es die Culture immer passend zu setzen je Context. Man will doch z.B. eigentlich immer eine andere Culture zum Datenaustausch (fix) als zur Anzeige (User abhängig).

Für diesen Beitrag haben gedankt: mats74
mats74 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 189
Erhaltene Danke: 26

Win 10
VS 2017/19, C++, C#
BeitragVerfasst: Di 28.10.14 08:02 
Hallo Ralf

Vielen Dank für Deine Ausführungen.

Ich habe folgenden Code in Startmethode eingefügt:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
static void Main()
{
  ...
  
  // Kultur definieren
  CultureInfo MeineKultur;
  MeineKultur = CultureInfo.CreateSpecificCulture("de-CH");
  Thread.CurrentThread.CurrentCulture = MeineKultur;
  Thread.CurrentThread.CurrentUICulture = MeineKultur;

  ...
}


Diese Definition übersteuert beim Windows 7 Rechner die manuellen Ländereinstellungen aus der Systemsteuerung korrekt.
Ausgabe: 1'310.0 wird also 1310.0

Beim Windows 8 Rechner wird trotzdem ein Komma anstelle des Punktes gesetzt (seit ca. 3 Wo / seit letztem Updatepacket)
Ausgabe: 1'310.0 wird 1 310,0 / Leerschlag und Komma (von irgendwoher) gesetzt
Diese Interpretation erhalte ich, wenn ich die Methode Convert.ToDouble() ausführe.

Wie kann ich diese Interpretation korrigieren, wo mache ich den Fehler?

Folgender Code bewirkt das Gleiche:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
...
Double d_meinezahl = 1000.1;
NumberFormatInfo nfi_meinformat = new CultureInfo("de_CH"false).NumberFormat;
nfi_meinformat.NumberGroupSeparator = "";
nfi_meinformat.NumberDecimalDigits = 1;
String s_meintext = d_meinezahl.ToString("N", nfi_meinformat);
...


Auf dem Windows 7 Rechner alles Korrekt.
Ausgabe: 1000.0

Windows 8 leider nicht.
Ausgabe: 1 000,0

Nun weiss ich leider nicht mehr weiter.
Das muss doch irgendwie aus dem Betriebssystem übersteuert werden oder liege ich da falsch?

Vielen Dank für Eure Bemühungen.

_________________
Gruss
mats74
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19273
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 28.10.14 10:01 
Die Ausgabe unter Windows 7 ist falsch, denn du benutzt als Ausgabetyp N. Und das bedeutet explizit mit Gruppentrennzeichen:
msdn.microsoft.com/d...ibrary/dwhawy9k.aspx
Dass ein leeres Trennzeichen funktioniert, ist eigentlich ein Fehler. Man kann das ja auch in den Regionseinstellungen nicht so einstellen, es kommt dann ein Fehler (unter Win 8.1 zumindest).

Wie wäre es mit F? Dann brauchst du auch nichts diesbezüglich umstellen. Bei mir wird es aber auch nicht ausgegeben, wenn ich deinen Code nutze, egal ob mit N oder F, und bei C auch nicht, wenn ich CurrencyGroupSeparator leer mache.

Nun zum Komma:
Das ist in der Schweiz ja korrekt als Dezimaltrennzeichen, es kann also durchaus sein, dass das Update das versehentlich umgestellt hat. Ausschließlich bei Währungswerten wird standardmäßig der Punkt benutzt. Stelle ich in den Regionseinstellungen das Dezimaltrennzeichen um, wird es auch so benutzt.

// EDIT:
Post noch etwas ausführlicher gestaltet

Für diesen Beitrag haben gedankt: mats74
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Di 28.10.14 10:39 
Zitat:
Das ist in der Schweiz ja korrekt als Dezimaltrennzeichen, es kann also durchaus sein, dass das Update das versehentlich umgestellt hat


connect.microsoft.co...r-ch-de-li-in-win8-1
mats74 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 189
Erhaltene Danke: 26

Win 10
VS 2017/19, C++, C#
BeitragVerfasst: Di 28.10.14 12:10 
Eure Ausführungen erklären eigentlich alles und bestätigen den Verdacht auf eine Umstellung im Windows 8.(,)1 Updatepacket :evil: .

Dies zeigt auch unsere "fehlerhafte" Programmierung in diesem Bereich.
Der bisherige Code war definitiv ein Zufallsprodukt von irgendwelchen Kulturdefault-Werten.
Also das vermeintlich Schlechte hat in diesem Fall wieder einmal auch etwas Gutes zur Folge :oops: .

Ich habe die Kultur folgendermassen abgefangen:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
...

Double d_meinezahl = 1000.1;
NumberFormatInfo nfi_meinformat = new CultureInfo("de_CH"false).NumberFormat;
nfi_meinformat.NumberGroupSeparator = "'";
nfi_meinformat.NumberDecimalSeparator = ".";
nfi_meinformat.NumberDecimalDigits = 1;
String s_meintext = d_meinezahl.ToString("N", nfi_meinformat);

...

... und erhalte dadurch auch die "korrekte" Schreibweise.
Diese Methode habe ich ausgelagert und verwende sie nun bei jeder Konvertierung einer Dezimalzahl.

Die Kultur "rm-CH"(rätromanische Schweiz) möchte ich lieber nicht verwenden, da wir unsere Software ein Bisschen weiter als nur das Bündnerland vertreiben :wink: .

Vielen Dank euch beiden.
Ihr habt mir sehr geholfen.

_________________
Gruss
mats74