c++ - 在 C++ 中制作可移植的字节序正确的文件读取/写入代码的简洁方法

标签 c++ boost endianness

我想编写一些 C++ 代码,以字节序正确的方式从文件中读取和写入。更准确地说,我希望能够读取特定类型的文件,我可以轻松检测到其字节顺序(其魔数(Magic Number)是否被反转)。

但是我该如何正确地干净地读取文件呢?我已阅读以下文章,其中提供了一个有用的想法:

http://www.gamedev.net/page/resources/_/technical/game-programming/writing-endian-independent-code-in-c-r2091

这里的想法是创建一个类,其中有一些函数指针指向所需的字节顺序正确的 read() 函数。但根据我的经验,函数指针很慢,尤其是当你必须像本例那样频繁地调用它们时。另一种选择是有一个

if (file_was_detected_big_endian) { read_bigendian(); } else { read_littleendian(); }

对于我拥有的每一个 read_x_bit_int() 函数,但这似乎也很低效。

我正在使用 Boost,所以我可以利用它的所有优势来帮助我。特别是,有 endian 子库:

http://www.boost.org/doc/libs/develop/libs/endian/doc/buffers.html

虽然我不确定如何才能干净地使用这段代码来做我想做的事。我希望有一些代码,我可以在其中直接读取 16 个字节到代表文件一部分的 struct 的指针中,同时自动更正字节顺序。我当然可以自己编写这段代码,但我觉得一定已经存在可靠的解决方案。

我认为我所有的代码都将被手动填充并防止对齐问题。

谢谢!

最佳答案

因此 dasblinkenlight 提出的虚函数方法可能就足够了 - 特别是因为 I/O 可能会成为时间的主要消耗者。但是,如果您确实发现您的读取函数占用了大量 CPU 时间,您可以通过模板化文件读取器来摆脱虚函数调度。

这里有一些伪代码演示了这一点:

基本上,创建两个读取器类,一个用于每个字节序:

class LittleReader {
  public:
  LittleReader(std::istream& is) : m_is(is) {}
  char read_char() {//read byte from m_is}
  int read_int32() {//read 32-bit int and convert;}
  float read_float()....
  private:
  std::istream& m_is;
};

class BigReader {
  public:
  BigReader(std::istream& is): m_is(is){}
  char read_char(){...}
  int read_int32(){..}
  float read_float(){...}
  private:
  std::istream& m_is;
}

将阅读逻辑的主要部分(魔数(Magic Number)位除外)分离到一个函数模板中,该模板将上述类之一的实例作为参数:

template <class Reader>
void read_endian(Reader &rdr){
  field1 = rdr.read_int32();
  field2 = rdr.read_float();
  // process rest of data file
  ...
}

从本质上讲,编译器将为您的 read_endian 函数创建两个实现 - 一个用于每个字节序。由于没有动态调度,编译器还可以内联所有对 read_int32、read_float 等的调用。

最后,在您的主要阅读器函数中,查看魔数(Magic Number)以确定要实例化哪种阅读器:

void read_file(std::istream& is){
  int magic(read_magic_no(is));
  if (magic == MAGIC_BIG_ENDIAN)
     read_endian(BigReader(is));
  else
     read_endian(LittleReader(is));
}

此技术为您提供了灵 active ,而不会产生任何虚拟分派(dispatch)开销,但会增加(二进制)代码大小。如果您的循环非常紧凑并且您需要压榨每一滴性能,它会非常有用。

关于c++ - 在 C++ 中制作可移植的字节序正确的文件读取/写入代码的简洁方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30467973/

相关文章:

c++ - 在 C 中初始化一个 char 数组。哪种方式更好?

c++ - 如何解析 POST body/GET 参数?

c++ - 复杂多边形的凸分解?

c++ - 用数组进行字节交换?

c++ - LNK1104 : cannot open file 'libboost_program_options-vc100-mt-sgd-1_56.lib'

c++ - Windows 中的 Control+Z 表示输入 C++ 结束?

boost - 无法在Windows 7 64位上的Cygwin下编译Boost 1.50.0

c++ - 字节序是否影响写入奇数个字节?

C# 小端还是大端?

c++ - 加载带有 362 项目的解决方案后,Win XP 上的 VS2005 SP1 崩溃,没有任何错误、日志或跟踪