2015-06-03 57 views
0

我希望能够将类型为Music的链接列表写入二进制文件,然后再将其读回链接列表。当然,我遇到问题了。据我所知,我的问题是字符串是一个可变长度。由于字符串并不总是相同的大小,所以在阅读时不知道要阅读多少。我打算将我的课程转换为固定长度的cstrings来解决问题。其实,我试过,但还有其他一些问题是由此造成的。我的问题是,有没有办法在不大幅改变我的代码的情况下达到我想要的效果?将二进制文件读入类对象

void ReadBinFile(Node * head, string filename) 
{ 
    Music new_song; 
    ifstream bin(filename, ios::in | ios::binary); 
    if (bin.is_open()) 
    { 
     while (!bin.eof()) 
     { 
      bin.read(reinterpret_cast<char *>(&new_song), sizeof(Music)); 
      if (!bin.eof()) 
      { 
       Node * new_node = CreateNode(new_song); 
       AppendNode(head, new_node); 
      } 
     } 
     bin.close(); 
    } 
} 
void Save(Node * head, string filename) 
{ 
    ofstream bin(filename, ios::out | ios::binary); 
    if (bin.is_open()) 
    { 
     Node * traveler = head; 
     while (traveler != nullptr) 
     { 
      bin.write(reinterpret_cast<char *>(&(traveler->song)), sizeof(Music)); 
      traveler = traveler->next; 
     } 
     bin.close(); 
    } 
} 
Node * CreateNode(Music song) 
{ 
    Node * new_node = new Node; 
    new_node->song = song; 
    new_node->next = nullptr; 

    return new_node; 
} 
//music.h 
class Music 
{ 
    public: 
     Music(string name = "", string artist = ""); 

    private: 
     string m_name; 
     string m_artist; 
}; 
+0

小心添加有关二进制文件格式如何的信息? –

+0

@Cyber​​Spock我会,但我不完全知道格式是什么。我对二进制文件了解不多。我可以复制+粘贴一个生成的例子,如果这会有所帮助。 –

+0

你需要先弄清楚格式,然后创建pack/unpack函数来读/写一条记录。 –

回答

1

做这样

bin.read(reinterpret_cast<char *>(&new_song), sizeof(Music)); 

不会有好下场,如果你看一下你的音乐类

class Music 
{ 
    public: 
     Music(string name = "", string artist = ""); 

    private: 
     string m_name; 
     string m_artist; 
    ... 

读只是简单地覆盖不考虑琴弦字符串模板实例化。

为了处理这种重载流操作符>><<,使你可以在你的代码从文件中读取这样的:

... 
Music song; 
bin >> song; 
... 

要做到这一点以外的音乐类的功能添加到打包和解包实例。

E.g.

std::ostream& operator<<(std::ostream& out, const Music &in) 
{ 
    return out << in.m_name.length() << in.m_name.c_str() 
     << in.m_artist.length() << in.m_artist.c_str(); 
} 

std::istream& operator>>(std::istream& is, Music &in) 
{ 
    // pseudo code 
    // read length, read characters of name put into "in" 
    // read length, read characters of artist put into "in" 
} 

这些函数中您将转换为您选择的二进制格式。二进制文件只是以原始方式解释的数据,并且与文本文件没有区别,该文本文件也是二进制文件,除非文件文件假定了某种格式,例如可读的字符和换行符。

如果你想以二进制形式存储,你需要找出一种方法来存储足够的信息,以便以后检索它。例如如果存储字符串,则可以先存储字符串的长度,然后存储字符串的长度,或者存储字符串并在末尾存在结尾\ 0,以便在读取字符串时知道何时停止。

+0

谢谢!我会在阅读本文时尝试一切,当我有时间时。 –

+0

很高兴我能帮忙,祝你好运! –

1

不幸的是,您使用的是字符串,它们是自己的类(具有动态分配的长度)。 如果你想写一个全班,它必须是全尺寸的,但即使这样我也不会推荐它。

将读取和写入方法添加到类中,并自己读取/写入每个字段。


作为一个澄清:
你想改变音乐那样:
class Music { public: Music(string name = "", string artist = ""); void Write(std::string filename); void Read(str::string filename); private: string m_name; string m_artist; };
然后你就可以二进制方式打开一个文件,写名字,然后写艺术家:
size_t len = str.size();
你写的长度字符串
file.write(reinterpret_cast<const char*>(&len), sizeof(len));
然后编写实际的字符串数据:
file.write(str.c_str(), len);


然后你用同样的方式阅读 - >你先阅读大小,然后阅读很多字符;)
它会重构你的代码,但我认为这将是正确的方式来做到这一点。

+0

谢谢!我不认为这会很简单。当我获得时间时我会试试看。你可能救了我很多压力。 –

+0

只要告诉我们是否有任何解决方案为您工作;) – MKK