Forum: PC-Programmierung [C++] Plattformunabhängiger stringstream


von Da D. (dieter)


Lesenswert?

Moin zusammen,

ich nutzte zur Serialisierung von Objekten std::stringstream. 
Funktioniert auch wunderbar. Aber ein stört mich daran noch: Das Format 
des erzeugten Strings hängt vom System locale setting ab. Damit kann ich 
keine Dateien erzeugen, die ohne Probleme auf andere Systeme übertragen 
werden können.

Dann dachte ich mir, ok ich geb ein fixes locale vor. Aber die locale 
Namen scheinen gemäß dieser Seite nicht standardisiert zu sein:
http://www.cplusplus.com/reference/locale/locale/locale/


Habt ihr ein Tipp wir ich am geschicktesten des erzeugten String 
plattformunabhängig bekomme?

von Daniel A. (daniel-a)


Lesenswert?

Die codierung UTF-8 wird von jeder ernstzunehmenden Platform 
unterstützt. Locale sind aber mehr als die Codierung, es gibt z.B. 
C.UTF-8 und en_US.utf-8, etc.

C.UTF-8 ist teil des POSIX standards, es sollte ihn fast überall geben, 
aber z.B. die sortierung von i,î und í nicht beieinander, sondern nach 
unicode wert, ich finde hier hat der POSIX standard versagt.

en_US.UTF-8 ist auf vielen Systemen vorhanden, aber nicht auf allen. 
Dafür werden i, î und í richtig sortiert.

Wenn die Sortierung einheitlich sein muss, und es nicht stört das i und 
î nicht intuitiv einsortiert werden, würde ich C.UTF-8 verwenden.
Wenn die Sortierung nicht einheitlich sein muss, würde ich versuchen die 
UTF-8 version des Systemlocales zu bekommen, ein fallback auf 
en_US.UTF-8 einbauen, und noch ein fallback auf C.UTF-8.

Ich glaube von den localen sind auch dinge wie Datumsformate abhängig. 
Ein riesen Chaos meiner meinung nach, ohne happyend.

von Klugscheißer (Gast)


Lesenswert?

Da D. schrieb:

> Dann dachte ich mir, ok ich geb ein fixes locale vor. Aber die locale
> Namen scheinen gemäß dieser Seite nicht standardisiert zu sein:
> http://www.cplusplus.com/reference/locale/locale/locale/
>
In deinem Link steht doch, daß die Locale "C" im Standard ist...

von Kaj (Gast)


Lesenswert?

schau doch einfach mal nach, wie die Leute das in der boost-Lib gelöst 
haben...

von Nase (Gast)


Lesenswert?

Da D. schrieb:
> ich nutzte zur Serialisierung von Objekten std::stringstream.
> Funktioniert auch wunderbar. Aber ein stört mich daran noch: Das Format
> des erzeugten Strings hängt vom System locale setting ab. Damit kann ich
> keine Dateien erzeugen, die ohne Probleme auf andere Systeme übertragen
> werden können.

Dann serialisiere halt in ein gescheites Format und nicht blindlings in 
einen stringstream.
Gibt doch Serialisierungs-Libs wie Sand am Meer. Schlimmstenfalls halt 
nach XML oder JSON oder sowas.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Da D. schrieb:
> Das Format des erzeugten Strings hängt vom System locale setting ab.
> Damit kann ich keine Dateien erzeugen, die ohne Probleme auf andere
> Systeme übertragen werden können.

Ich nehme an, dir geht es um solche Dinge wie Dezimaltrennzeichen (Punkt
oder Komma) u.ä.

Dateien, über die Daten zwischen mehreren Anwendungen übertragen werden,
sollten von diesen immer mit Locale "C" geschrieben und gelesen werden.
Das Default-Locale in C++ (wie auch in C) ist "C". Deswegen entstehen
normalerweise keine Probleme, solange man innerhalb der Programme
nirgends an den Locales herumpfuscht.

In C++ kann man das Locale für jeden Stream getrennt mit der Methode
imbue() einstellen. Tut man das nicht, wird als Locale das mit
std::locale::global() gesetzte globale Locale verwendet. Wurde das
globale Locale nicht explizit gesetzt, ist es "C".

Es ist in C++ i.Allg. unklug, das globale Locale zu setzen, da man damit
früher oder später oft auf die Nase fällt.

Falls du das globale Locale nicht selbst gesetzt hast, kann es sein,
dass das irgendeine übereifrige Bibliothek (bspw. ein GUI-Toolkit) für
dich gemacht hat, um dich zu ärgern. In diesem Fall hast du zwei
Möglichkeiten:

1. Du sagst der Bibliothek, dass sie das globale Locale nicht setzen
   soll (falls das möglich ist).

2. Du setzt für deinen stringstream das Locale mit imbue() explizit auf
   "C" oder std::locale::classic(), was beides dasselbe ist.

von Da D. (dieter)


Lesenswert?

Sorry, bin erst heute wieder dazu gekommen, mich um das Thema zu 
kümmern.

Yalu X. schrieb:
> Dateien, über die Daten zwischen mehreren Anwendungen übertragen werden,
> sollten von diesen immer mit Locale "C" geschrieben und gelesen werden.
> Das Default-Locale in C++ (wie auch in C) ist "C". Deswegen entstehen
> normalerweise keine Probleme, solange man innerhalb der Programme
> nirgends an den Locales herumpfuscht.

Danke, für die Aufklärung. Ich hatte das beim Lesen auf cplusplus.com 
anders interpretiert. Ich dachte, dass wenn "C" das default loacle ist, 
dass man damit wieder auf das locale, welches auf dem System eingestellt 
ist, zurück schalten kann. Aber so wie du schreibst, kann ich einfach 
zur Sicherheit auf "C" schalten, und müsste auf der sicheren Seite sein. 
Dankeschön!

von Da D. (dieter)


Lesenswert?

Nase schrieb:
> Dann serialisiere halt in ein gescheites Format und nicht blindlings in
> einen stringstream.
> Gibt doch Serialisierungs-Libs wie Sand am Meer. Schlimmstenfalls halt
> nach XML oder JSON oder sowas.

Die Antwort kann ich mir jetzt doch nicht verkneifen:
Ja, hast recht, ich sollte in ein gescheites Format serialisieren. 
Deswegen nehme ich XML. Aber Moment, XML ist ja ein Textformat, dazu 
muss ich ja Binärdaten in Strings verwandeln. Und dazu nehme ich, 
Überraschung, einen stringstream ;-)

von Nase (Gast)


Lesenswert?

Da D. schrieb:
> Nase schrieb:
>> Dann serialisiere halt in ein gescheites Format und nicht blindlings in
>> einen stringstream.
>> Gibt doch Serialisierungs-Libs wie Sand am Meer. Schlimmstenfalls halt
>> nach XML oder JSON oder sowas.
>
> Die Antwort kann ich mir jetzt doch nicht verkneifen:
> Ja, hast recht, ich sollte in ein gescheites Format serialisieren.
> Deswegen nehme ich XML. Aber Moment, XML ist ja ein Textformat, dazu
> muss ich ja Binärdaten in Strings verwandeln. Und dazu nehme ich,
> Überraschung, einen stringstream ;-)
Ja und nein.

XML ist im Prinzip schon ein Textformat, ja.
Schon mit XML Schema (vmtl. auch den meisten anderen Schemasprachen) 
kannst du aber gezielt Datentypen festlegen, so dass z.B. irgendwo ein 
"double" stehen soll. Damit ist dann auch schon vereinbart, wie der 
auszusehen hat[1]

Praktisch dürfte das wohl immer auf irgendwas ähnlich zu stringstream 
mit C-locale hinaus.


[1] http://www.w3.org/TR/xmlschema-2/#double

von Nase (Gast)


Lesenswert?

Soll heißen: XML ist zwar ein Textformat, aber es gibt in XML auch 
Datentypen.

Auch viele andere Serialisierungen erzeugen "Textformat". Aber auch dort 
ist dann festgelegt, wie die Datentypen zu Text werden und wie man vom 
Text wieder zum Datentyp kommt.
Genau das ist ja grad der Sinn von solchen Serialisierungen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.