2009-12-02 46 views
8

我有代码,使用fstream操作二进制文件与二进制标志设置和使用未格式化的I/O函数读取和写入。这在我使用过的所有系统上都能正常工作(文件中的位与预期完全相同),但这些基本上都是美国英语。我一直想知道这些字节在不同的系统上被codecvt修改的可能性。使用C++编写二进制文件:默认语言环境很重要吗?

听起来像标准所说的,使用无格式I/O的行为与使用sputc/sgetc将字符放入streambuf中的行为相同。这些会导致streambuf中的溢出或下溢函数被调用,并且听起来像这些会导致经历一些codecvt(例如,参见C++标准中的27.8.1.4.3)。对于basic_filebuf,这个codecvt的创建在27.8.1.1.5中指定。这使得它看起来像结果将取决于basic_filebuf.getloc()返回的内容。

所以,我的问题是,我可以假设在一个系统上使用ofstream.write写出的字符数组可以在另一个系统上使用ifstream.read逐字恢复,无论任何人可能使用哪种语言环境配置系统?我会做如下假设:

  1. 程序正在使用默认 区域(即程序不 更改区域设置本身 在所有)。
  2. 系统都有CHAR_BIT 8,在每个字节内具有相同的位顺序,将文件存储为八位位组等。
  3. 流对象具有设置的二进制标志。
  4. 在这个阶段,我们不需要担心任何永久性差异。如果数组中的任何字节将被解释为多字节值,则将在稍后的阶段根据需要处理字节顺序转换。

如果默认语言环境不能保证在某些系统配置(我不知道,阿拉伯语或其他)上未经修改就通过这个东西,那么使用C++编写二进制文件的最佳方式是什么?

+1

我认为你应该添加相同的字节顺序到你的假设。还是我完全在那里? – 2009-12-02 08:20:19

+0

@TheScottMachine:Space_C0wb0y是正确的,将相同的字节顺序添加到您的假设 – Stan 2009-12-02 23:51:19

+0

谢谢,我添加了一个额外的假设来澄清。 – TheScottMachine 2009-12-03 02:22:49

回答

0

在Windows上应该没问题,但在其他操作系统上,您还应该检查行结尾(就像安全一样)。默认的C/C++语言环境是“C”,它是而不是,具体取决于系统的语言环境。

这不是保证。正如你所了解的C/C++编译器和他们的目标机器差别很大。所以如果你保留所有这些假设,你就等着麻烦来了。改变语言环境的开销可以忽略不计,除非你试图让它每秒数百次。

+0

谢谢,有关默认语言环境的信息是我正在寻找的。 我认为只要在流上设置了二进制标志,行结束就不应该出现问题。 – TheScottMachine 2009-12-04 02:40:23

1

如果您设置了二进制标志,则您写入的所有内容都将逐字写入该文件。没有转换。你如何解释字节取决于你(可能还有语言环境)。

还有一件事:在不同的语言环境中有破损的可能性。例如,如果您的数据源基于语言环境创建二进制数据(并且此数据的格式会根据语言环境而改变 - 这是一个糟糕的主意btw)。在不同语言环境的机器上加载数据时会造成麻烦。但这是一个设计错误。

如果您只是使用具有相同格式/布局的标准数据类型/结构,而不管它们在任何地方创建的语言环境都应该是OK。

1

感谢您的帮助。我只是认为,发布一些不适合评论的附加信息可能会有帮助。

C++程序的默认语言环境始终为“C”语言环境(http://www.cplusplus.com/reference/clibrary/clocale/setlocale/)。如果这是您的程序中唯一使用的语言环境,则意味着该行为不依赖于其所运行的计算机的特定语言环境配置。这也意味着一个char的未格式化的I/O不会经历任何代码转换(尽管wchar_t可能是一个不同的故事)。这意味着(考虑到问题中的假设)读取和写入应该允许二进制数据未修改地被恢复。

(来自阅读文档)您可以通过调用setlocale(LC_ALL,“”)全局设置应用程序的语言环境以匹配系统默认值,这意味着从该点构建的流将使用系统默认语言环境。要将其设置回“C”语言环境,您可以调用setlocale(LC_ALL,“C”),这意味着这是未来构建的流将使用的语言。你也可以通过调用stream.imbue(locale :: classic())来指定“C”local应该用于已经构建的流。

相关问题