使用C ++编写二进制文件:默认语言环境是否重要?

时间:2009-12-02 08:12:57

标签: c++ binary locale fstream

我有使用fstream操作二进制文件的代码,其中设置了二进制标志并使用未格式化的I / O函数进行读写。这在我曾经使用的所有系统上都能正常工作(文件中的位完全符合预期),但这些基本上都是美国英语。我一直想知道这些字节可能被不同系统上的codecvt修改。

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

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

  1. 该程序使用默认值 区域设置(即程序不是 更改区域设置本身 在所有)。
  2. 系统都有CHAR_BIT 8,每个字节内的位顺序相同,存储文件为八位字节等。
  3. 流对象设置了二进制标志。
  4. 我们不需要担心此阶段的任何结束差异。如果要将数组中的任何字节解释为多字节值,则将在稍后阶段根据需要处理字节顺序转换。
  5. 如果默认语言环境无法保证在某些系统配置(我不知道,阿拉伯语或其他东西)上未修改此内容,那么使用C ++编写二进制文件的最佳方法是什么?

3 个答案:

答案 0 :(得分:1)

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

还有一件事:不同的语言环境可能会出现破损。例如,如果您的数据源基于区域设置创建二进制数据(并且此数据的格式将根据区域设置而改变 - 这是一个坏主意btw)。在具有不同语言环境的计算机上加载数据时,这会导致问题。这是一个设计错误。

如果您只使用具有相同格式/布局的标准数据类型/结构,无论它们在一切中创建的区域设置都应该没问题。

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:0)

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

这不是保证。如您所知,C / C ++编译器及其目标机器差别很大。所以如果你保留所有这些假设,你就等待麻烦来了。除非您尝试每秒数百次,否则更改区域设置的开销可以忽略不计。