跨平台编程问题(文件I/O) 我有一个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; } #pragma pack(push, 1) struct Header { // This struct uses 1-byte padding ... }; #pragma pack(pop) class二进制流:私有std::iostream { 公众: 显式二进制流(const std::string和文件名); bool read(); bool write(); 私人: 标题m_hdr; std::向量m_行; }

跨平台编程问题(文件I/O) 我有一个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; } #pragma pack(push, 1) struct Header { // This struct uses 1-byte padding ... }; #pragma pack(pop) class二进制流:私有std::iostream { 公众: 显式二进制流(const std::string和文件名); bool read(); bool write(); 私人: 标题m_hdr; std::向量m_行; },c++,cross-platform,ubuntu-9.04,C++,Cross Platform,Ubuntu 9.04,此类以二进制格式将数据读写到磁盘。我没有使用任何特定于平台的编码,而是依赖于STL。我已经成功地在XP上编译了。我想知道我是否可以用FTP传输在XP平台上编写的文件,并在我的Linux机器上读取它们(一旦我在Linux上重新编译二进制流库) 总结: 使用为Xp编译的跨平台库在Xp计算机上创建的文件 在Linux机器上编译相同的库(在上面的1中使用) 问题:上面1中创建的文件能否在Linux机器上读取(2) 如果没有,请解释为什么没有,以及我如何解决这个问题。只要它是纯二进制文件,它就应该工作只要

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

总结:

  • 使用为Xp编译的跨平台库在Xp计算机上创建的文件
  • 在Linux机器上编译相同的库(在上面的1中使用)
  • 问题:上面1中创建的文件能否在Linux机器上读取(2)


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

    只要它是纯二进制文件,它就应该工作

    只要它是纯二进制文件,它就应该工作

    ,因为你使用STL做任何事情,没有理由你的程序不能在不同的平台上读取文件。

    因为你什么都用STL,没有理由你的程序不能在不同的平台上读取文件。

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

    您还可能会遇到与行尾字符相关的问题。这里没有足够的关于如何使用
    ::std::iostream
    的信息为您提供这个问题的好答案


    我强烈建议你看一下这本书。它是创建快速跨平台二进制编码的优秀库。

    这完全取决于二进制编码的具体情况。Linux与XP的一个不同之处在于,您更可能发现自己处于一个大端机平台上,如果您的二进制编码是特定于端机的,那么最终会出现问题

    您还可能会遇到与行尾字符相关的问题。这里没有足够的关于如何使用
    ::std::iostream
    的信息为您提供这个问题的好答案


    我强烈建议你看一下这本书。它是创建快速跨平台二进制编码的优秀库。

    源自
    std::basic\u streambuf
    。这就是他们在那里的目的。请注意,大多数STL类的设计目的不是从中派生。我提到的是一个例外。

    源自
    std::basic\u streambuf
    。这就是他们在那里的目的。请注意,大多数STL类的设计目的不是从中派生。我提到的是一个例外。

    如果你想让你的代码可以在不同端号的机器上移植,你需要坚持在你的文件中使用一个端号。无论何时读取或写入文件,都会在主机字节顺序和文件字节顺序之间进行转换。当您想要编写可跨所有机器移植的文件时,通常使用您称之为网络字节顺序的方法。网络字节顺序被定义为big-endian,并且有预先制作的函数来处理这些转换(尽管它们很容易自己编写)

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

    如果您不关心支持big-endian系统,那么这一切都不是问题,尽管这仍然是一个很好的实践

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

    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;        
    }
    
    #pragma pack(push, 1)
    struct Header {
      // This struct uses 1-byte padding
      ...
    };
    #pragma pack(pop)
    
    请记住,在应用程序中使用该结构时,这样做会使使用该结构的效率更低,因为访问未对齐的内存地址意味着系统要做更多的工作。这就是为什么通常最好为写入流的压缩结构使用单独的类型,以及在应用程序中实际使用的类型(只需将成员从一个复制到另一个)


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

    如果您想让代码能够跨具有不同端点的机器进行移植,您需要坚持在文件中使用一个endianess。无论何时读取或写入文件,都会在主机字节顺序和文件字节顺序之间进行转换。当您想要编写可跨所有机器移植的文件时,通常使用您称之为网络字节顺序的方法。网络字节顺序被定义为big-endian,并且有预先制作的函数来处理这些转换(尽管它们很容易自己编写)

    例如,在将long写入文件之前,应使用htonl()将其转换为网络字节顺序,在读取文件时,应使用ntohl()将其转换回主机字节顺序。关于big-endian系统htonl()和ntohl()si