Binärdateien mit C ++ schreiben: Ist das Standardgebietsschema wichtig?

8

Ich habe Code, der Binärdateien manipuliert, indem er fstream mit dem gesetzten binären Flag verwendet und die unformatierten E / A-Funktionen liest und schreibt. Dies funktioniert auf allen Systemen, die ich je benutzt habe (die Bits in der Datei sind genau wie erwartet), aber das sind im Grunde alle US-Englisch. Ich habe mich gefragt, ob diese Bytes möglicherweise von einem Codecvt auf einem anderen System geändert werden.

Es klingt wie im Standard, dass die Verwendung unformatierter E / A sich genauso verhält wie das Einfügen von Zeichen in den Stream mit sputc / sgetc. Dies führt zu den Überlauf- oder Unterlauffunktionen im aufgerufenen streambuf, und es hört sich so an, als würden diese zu einem Codecvt führen (siehe beispielsweise 27.8.1.4.3 im C ++ - Standard). Für basic_filebuf ist die Erstellung dieses Codecvt in 27.8.1.1.5 angegeben. Das sieht so aus, als ob die Ergebnisse davon abhängen, was basic_filebuf.getloc () zurückgibt.

Also, meine Frage ist, kann ich annehmen, dass ein Character-Array, das mit ofstream.write auf einem System geschrieben wurde, wörtlich mit ifstream.read auf einem anderen System wiederhergestellt werden kann, egal welche Locale-Konfiguration eine Person auf ihrem System verwendet ? Ich würde die folgenden Annahmen treffen:

  1. Das Programm verwendet den Standard Gebietsschema (d. h. das Programm ist nicht Ändern der Gebietsschemaeinstellungen selbst überhaupt).
  2. Die Systeme haben beide CHAR_BIT 8, haben die gleiche Bit-Reihenfolge innerhalb jedes Bytes, speichern Dateien als Oktette, etc.
  3. Die Stream-Objekte haben das binäre Flag gesetzt.
  4. Wir müssen uns in diesem Stadium keine Gedanken über Endianess-Unterschiede machen. Wenn irgendwelche Bytes in dem Array als ein Multi-Byte-Wert interpretiert werden sollen, werden Endianitätsumwandlungen wie erforderlich zu einem späteren Zeitpunkt gehandhabt.

Wenn das Standardgebietsschema bei einigen Systemkonfigurationen nicht garantiert ist (ich weiß nicht, Arabisch oder so), was ist dann der beste Weg, Binärdateien mit C ++ zu schreiben?

    
TheScottMachine 02.12.2009, 08:12
quelle

3 Antworten

0

Unter Windows sollte es in Ordnung sein, aber auf anderen Betriebssystemen sollten Sie auch die Zeilenenden überprüfen (genauso wie die Sicherheit). Das Standard-C / C ++ - Gebietsschema ist "C", was abhängig von der Ländereinstellung des Systems nicht ist.

Dies ist keine Garantie. Wie Sie wissen, variieren C / C ++ - Compiler und ihre Zielrechner stark. Sie warten also auf Probleme, wenn Sie all diese Annahmen beibehalten. Es gibt einen vernachlässigbaren Overhead für das Ändern des Gebietsschemas, es sei denn, Sie versuchen, es in Hunderten von Sekunden pro Sekunde zu machen.

    
Wernight 02.12.2009, 08:40
quelle
1

Wenn Sie das binäre Flag gesetzt haben, wird alles, was Sie schreiben, wörtlich in die Datei geschrieben. Keine Conversions Wie Sie die Bytes interpretieren, liegt an Ihnen (und möglicherweise an der Ländereinstellung).

Noch eine Sache: Es gibt eine Möglichkeit zu brechen an verschiedenen Orten. Wenn Ihre Datenquelle beispielsweise binäre Daten basierend auf dem Gebietsschema erstellt hat (und das Format dieser Daten sich je nach Gebietsschema ändern würde - das ist eine schlechte Idee, btw). Dies würde beim Laden von Daten auf Maschinen mit unterschiedlichen Ländereinstellungen zu Problemen führen. Dies ist jedoch ein Konstruktionsfehler.

Wenn Sie nur Standarddatentypen / Strukturen verwenden, die dasselbe Format / Layout haben, egal in welchem ​​Gebietsschema sie erstellt wurden, sollte alles in Ordnung sein.

    
Stan 03.12.2009 00:04
quelle
1

Danke für die Hilfe. Ich dachte nur, es könnte hilfreich sein, einige zusätzliche Informationen darüber zu veröffentlichen, die nicht in einen Kommentar passen würden.

Das Standardgebietsschema für C ++ - Programme ist immer das Gebietsschema "C" ( Ссылка ). Wenn dies das einzige in Ihrem Programm verwendete Gebietsschema ist, bedeutet dies, dass das Verhalten nicht von der jeweiligen Gebietsschema-Konfiguration des Computers abhängt, auf dem es ausgeführt wird. Es bedeutet auch, dass unformatierte I / O für einen Char keine Code-Konvertierung unterzogen wird (wchar_t könnte jedoch eine andere Geschichte sein). Dies bedeutet, dass Lesen und Schreiben (angesichts der Annahmen in der Frage) ermöglichen sollte, dass Binärdaten unverändert wiederhergestellt werden können.

(aus dem Lesen der Dokumentation) Sie können das Gebietsschema der Anwendung global auf den Systemstandard einstellen, indem Sie setlocale (LC_ALL, "") aufrufen, was bedeutet, dass die von diesem Punkt erstellten Streams das Standardgebietsschema des Systems verwenden. Um es auf das Gebietsschema "C" zurückzusetzen, können Sie setlocale (LC_ALL, "C") aufrufen, was bedeutet, dass dies für die in Zukunft erstellten Streams verwendet wird. Sie können auch angeben, dass "C" local für einen Stream verwendet werden soll, der bereits durch Aufrufen von stream.imbue (locale :: classic ()) erstellt wurde.

    
TheScottMachine 04.12.2009 02:50
quelle

Tags und Links