Wie behebt man eine Anwendung, die ein Problem mit dem Dezimaltrennzeichen hat

8

In diesem Beitrag geht es um C # und .Net, aber einige Informationen sind wertvoll für andere techonolgies.

Seit ich mich erinnern kann, habe ich Probleme mit Apps oder Spielen, die aufgrund eines anderen Typs der Syntaxanalyse von Dezimalzahlen abstürzen. Es passiert sehr oft, von CAD-Apps, Bibliotheken bis hin zu Webseiten. Ich bin mir nicht sicher, ob es Unwissenheit oder Unwissenheit ist, aber es ist wirklich nervig.

Was ist das Problem? Hier ist ein Wiki-Artikel darüber, aber es ist kurz:

Hier ist eine Karte, die zeigt, welche Art von Dezimaltrennzeichen (Dezimalzeichen) auf der ganzen Welt verwendet wird.

Dezimalzeichen:

  • Periode - Blau
  • Komma - Grün
  • Nicht-west-arabische Ziffern - Rot
  • Unbekannt - Grau

Die meisten Europa, Südamerika schreiben 1 000 000,00 oder 1000000,00 manchmal 1.000.000,00 im Gegensatz zu "imperial" (markiert als blau) schreiben 1.000.000,00

Lassen Sie mich Ihnen nur einige von allen Problemen nennen, die ich letzten Monat erfahren habe.

  1. Nummer auf schwer lesbaren Webseiten: Nehmen wir eine der angesehenen YT-Videos . Es zeigt mir 390159851. Zahlen über einer Million sind sehr schwer zu lesen, was ist die Größenordnung? Ist es 39 Millionen oder 390?
  2. Mirosoft XNA für Windows Phone 7 Beispiel : Es gibt eine sehr gute Klasse, die XML-Dateien analysiert um XNA Animation zu produzieren

    %Vor%

    double.Parse löst eine Ausnahme aus, eine einfache Lösung ist XmlConvert.ToDouble(); zu verwenden oder mit InvariantCulture zu analysieren.

  3. .Net-App, die CSV-Dateien verwenden, um Eingabe-Vektor als CSV zu speichern - wirft auch.

  4. Eine weitere .Net-App, die in der Klasse ein Parsing durchführt - throws.

Wie können wir das beheben?

  • Beheben Sie den Fehler im Code - nur mit verfügbarem Quellcode und langwierig.
  • Ändern Sie die Daten (CVS, XML etc.) - auch mit möglichen, nicht sehr zufrieden mit den Daten mutieren.
  • Ändern Sie das Standard-Dezimaltrennzeichen des Betriebssystems - das wird nicht passieren.

Gibt es eine andere Möglichkeit, dies zu ändern? Kann ich die App invariant machen? Wie das Starten der App in einer anderen Umgebung.

PS. Ich möchte die App ausführen, aber ich habe den Code nicht.

    
Lukasz Madon 21.06.2011, 16:21
quelle

5 Antworten

5

Setzen Sie Thread.CurrentThread.CurrentCulture richtig und Sie haben solche Probleme nicht. Lesen Sie hier , wie Sie kulturunabhängigen Code schreiben können.

BEARBEITEN: Wenn Sie keinen Zugriff auf den Code haben, können Sie die Anwendung unter einem Benutzerkonto ausführen, das den erwarteten Kultursatz aufweist. Für den schnellen Zugriff können Sie einen englischen Benutzer, einen deutschen Benutzer, einen französischen Benutzer erstellen.

    
codymanix 21.06.2011, 16:26
quelle
1

Meiner Meinung nach sollte der Ansatz folgen:

  1. im internen Speicher sind die Zahlen nur Zahlen. also kein Problem auftritt.
  2. Wenn Sie Eingabetextquellen analysieren, sollten Sie sie entsprechend der Ländereinstellung analysieren, in der die Quelle erstellt wird - höchstwahrscheinlich invariante Kultur
  3. Wenn Sie die Werte an den Benutzer ausgeben, formatieren Sie sie nach dem vom Benutzer bevorzugten Gebietsschema. in C # bedeutet dies, dass CurrentCulture (nicht CurrentUICulture , siehe hier warum) beibehalten wird.

Dies sollte relativ einfach sein und alle Fälle abdecken.

Dies alles gilt für den Fall, dass Sie der Autor der Anwendung sind. Für andere Anwendungen müssen die jeweiligen Entwickler ihre Fehler selbst beheben.

    
Vlad 21.06.2011 16:29
quelle
1

Ich fühle Ihre Schmerzen, der Port von RunKeeper an Windows Phone 7 hat das falsch verstanden und berichtet, dass ich die Lichtgeschwindigkeit um einen Faktor von 100 000 im letzten Monat gebrochen habe.

Wenn Sie schlampig sind, werden Sie auf diese Probleme stoßen, aber in den meisten Fällen können sie vermieden werden. Streng genommen sollten Sie Informationen immer in ihrem lokalisierten Format präsentieren und sie dann in einen kulturunabhängigen oder Basiswert konvertieren, wenn Sie sie speichern. Auf diese Weise können Sie immer gezielt auf bestimmte Kulturen abzielen.

Das Problem, auf das viele .NET-Entwickler stoßen, ist, dass sie nicht verstehen, dass alle Standardmethoden für Parsing-Methoden auf Thread.CurrentThread.CurrentCulture zurückgreifen und ein bestimmtes Zahlenformat für diese Kultur verwenden. Dasselbe gilt für Datums- und Zeitzonen .

Etwas, das ich in Betracht ziehen könnte, ist eine Kette von Verantwortlichkeiten aufzubauen, in der ich zuerst die kulturspezifischen Varianten und ein kulturinvariantes Fallback abgefragt habe. Ich würde diese niemals mischen, aber ich würde einen kulturunabhängigen Standard unterstützen, der funktionieren sollte, wenn Sie sich an eine typische Konvention halten (z. B. englische Zahlenformate). Aber das ist nicht immer die richtige Wahl, erziehen Sie Benutzer, wenn sie denken, dass die Analyse einer CSV-Datei mit gemischtem Zahlenformat eine gute Sache ist.

    
John Leidegren 21.06.2011 16:37
quelle
1

Hier ist keine Silberkugel.

Einige Vorschläge:

Die invariante Kultur kann verwendet werden, wenn interne Daten behandelt werden, die in einer Konfigurationsdatei gespeichert sind. Auf diese Weise können Sie unabhängig von der Kultur der Maschine Ihre eigenen internen Daten konsistent lesen und schreiben.

Siehe hier:

Ссылка

Andere Probleme behandeln etwas Einfaches wie string.ToLower ().

Scheint unschuldig genug, bis Sie versuchen, einen englischen Buchstaben in Kleinbuchstaben zu schreiben, als in der aktuellen Kultur nicht vorhanden ist. (E.G. Türkisch)

In diesen Fällen sollte der Aufruf von string.ToLower () durch die Kulturüberladung ersetzt werden und die aktuelle Kultur oder invariante Kultur sollte übergeben werden (abhängig von Ihrer Situation).

Auf jeden Fall einige Fallen, auf die man achten sollte.

    
Jon Raynor 21.06.2011 17:00
quelle
1

Es gibt wirklich keine andere Möglichkeit, dieses Problem zu lösen, indem Sie es einfach im Code reparieren.
Wenn Sie FxCop ausführen möchten, würden Sie schnell lernen, immer zu bleiben Übergeben Sie CultureInfo an alle möglichen Methoden ToString() oder Parse() . Ehrlich gesagt, sollte dies so gemacht werden, auch wenn Sie wissen, dass CultureInfo.CurrentCulture standardmäßig verwendet wird.
Indem Sie IFormatProvider immer übergeben, sagen Sie anderen Entwicklern:

  1. ToString(CultureInfo.CurrentCulture) oder Parse(whatever, CultureInfo.CurrentCulture) - dies ist etwas, was der Endbenutzer sehen wird oder in Zukunft betreten kann. Daher müssen wir uns um seinen kulturellen Hintergrund kümmern.
  2. ToString(CultureInfo.InvariantCulture) oder Parse(whatever, CultureInfo.InvariantCulture) - dies verwenden wir intern und es ist nicht dazu gedacht, dem Benutzer angezeigt zu werden.

Nun, ich weiß, es klingt nach viel Arbeit, aber das ist einfach etwas, was getan werden muss. Vielleicht möchten Sie nur einigen armen Menschen in Microsoft danken, die mit ihrer guten Absicht entschieden haben, dass CurrentCulture des Endbenutzers der beste Standard für Formatierungs-Anbieter ist ... Offensichtlich waren andere Framework-Designer, die das in der Vergangenheit taten, falsch und Leute aus MS haben recht, ha? Eine Menge Geld ist durch diesen blöden, unflexiblen Fehler verloren gegangen.

    
Paweł Dyda 21.06.2011 17:03
quelle