1

我有一个看起来有点像这样的 C++ 类:

class BinaryStream : private std::iostream
{
    public:
        explicit BinaryStream(const std::string& file_name);
        bool read();
        bool write();

    private:
        Header m_hdr;
        std::vector<Row> m_rows;        
}

这个类以二进制格式读取和写入数据到磁盘。我没有使用任何特定于平台的编码——而是依赖于 STL。我已经在XP上成功编译。我想知道我是否可以将在 XP 平台上编写的文件 FTP 并在我的 Linux 机器上读取它们(一旦我在 Linux 上重新编译二进制流库)。

概括:

  1. 使用为 XP 编译的跨平台库在 Xp 机器上创建的文件。
  2. 在 Linux 机器上编译相同的库(在上面 1 中使用)

问题:上面1中创建的文件可以在Linux机器(2)上读取吗?

如果不是,请解释为什么不,以及我如何解决这个问题。

4

7 回答 7

1

这完全取决于二进制编码的细节。Linux 与 XP 的不同之处在于,您更有可能在大端平台上发现自己,如果您的二进制编码是特定于端的,您最终会遇到问题。

您可能还会遇到与行尾字符相关的问题。这里没有足够的信息来说明你是如何使用::std::iostream这个问题来给你一个很好的答案的。

我强烈建议查看protobuf 库。它是创建快速跨平台二进制编码的优秀库。

于 2009-10-28T07:04:25.117 回答
1

源自std::basic_streambuf. 这就是他们的目的。请注意,大多数 STL 类并非旨在派生自。我提到的是一个例外。

于 2009-10-28T07:09:03.810 回答
1

如果您希望您的代码可跨具有不同字节序的机器移植,则需要坚持在文件中使用一种字节序。每当您读取或写入文件时,您都会在主机字节顺序和文件字节顺序之间进行转换。当您要编写可在所有机器上移植的文件时,通常会使用所谓的网络字节顺序。网络字节顺序被定义为大端,并且有预先制作的函数来处理这些转换(虽然它们很容易自己编写)。

例如,在将 long 写入文件之前,应使用 htonl() 将其转换为网络字节顺序,当从文件读取时,应使用 ntohl() 将其转换回主机字节顺序。在大端系统上,htonl() 和 ntohl() 只返回与传递给函数的相同数字,但在小端系统上,它交换变量中的每个字节。

如果您不关心支持大端系统,那么这些都不是问题,尽管它仍然是一种很好的做法。

另一个需要注意的重要事情是填充您编写的结构/类,如果您将它们直接写入文件(例如,标题和行)。不同平台上的不同编译器可以使用不同的填充,这意味着变量在内存中的对齐方式不同。如果您在不同平台上使用的编译器使用不同的填充,这可能会严重破坏事情。因此,对于您打算直接写入文件/其他流的结构,您应该始终指定填充。你应该告诉编译器像这样打包你的结构:

#pragma pack(push, 1)
struct Header {
  // This struct uses 1-byte padding
  ...
};
#pragma pack(pop)

请记住,当您在应用程序中使用该结构时,这样做会降低使用该结构的效率,因为访问未对齐的内存地址意味着系统需要做更多的工作。这就是为什么为写入流的打包结构和在应用程序中实际使用的类型(您只需将成员从一个复制到另一个)具有单独的类型通常是一个好主意的原因。

编辑。当然,另一种处理该问题的方法是自己序列化这些结构,这不需要使用#pragma(编译指示是编译器相关的功能,尽管据我所知所有主要编译器都支持编译指示包)。

于 2009-10-28T07:37:31.747 回答
1

这是与您的问题相关的文章字节顺序。查找“文件和字节交换中的字节顺序”。简而言之,如果您的 Linux 机器具有相同的字节序,则可以,如果没有,则可能会出现问题。

例如,当整数 1 写入 XP 上的文件时,它看起来像这样:10 00

但是当整数 1 以其他字节顺序写入机器上的文件时,它将如下所示:00 01

但是如果你只使用一个字节的字符肯定没有问题。

于 2009-10-28T07:38:46.403 回答
0

只要它是普通的二进制文件,它就可以工作

于 2009-10-28T07:01:24.170 回答
0

因为您对所有内容都使用 STL,所以您的程序没有理由不能读取不同平台上的文件。

于 2009-10-28T07:02:41.050 回答
0

如果您将结构/类直接写入光盘,则不要。

这可能在同一编译器上的不同构建之间不兼容,并且几乎可以肯定当您移动到不同的平台或编译器时会中断。如果您更改为不同的架构,它肯定会崩溃。

从上面的代码中并不清楚您实际写入文件的内容。

于 2009-10-28T07:41:18.427 回答