870920 Menu

JUCE类库FileBasedDocument详解

先了解一下程序中读写文件的大体流程(分两种情况):

  1. 从无到有的生成文件。运行程序,内部创建各种各样的数据类型和数据对象,一番操作处理后,将数据保存到磁盘文件中。该过程往往利用临时创建或某些类一直持有的XmlElement、ValueTree、JSON等对象(数据模型)来读取、计算和设置(修改、新增等等)各种数据。如有需要时,将这些对象中的数据保存到磁盘文件中。
  2. 读写已有的数据文件。和上个情况差不多,所不同的,内部的数据模型对象在创建时即直接初始化为磁盘文件中的数据,即:先加载和读取磁盘文件中的数据,将所需的数据设置到数据模型中(比如XmlElement对象的属性值)。而后,针对这些数据模型的对象进行读取和设置操作,处理完毕,将数据回写到磁盘文件中。

以上流程,有3个关键点:

  1. 加载磁盘文件,读取文件中的数据,将数据转为程序内部的对象。
  2. 程序内部对数据模型进行各类读写、增删改等处理。
  3. 保存磁盘文件(即程序内部的数据写入磁盘文件中)。

第2个关键点是应用程序的业务逻辑与功能核心,涉及广泛,很难一言蔽之,暂且不论。第1和第3个关键点代表了程序处理数据的来源与终点,其重要性同样不言而喻。常规模式下,这两个关键点的编码量、复杂度与繁琐性均不容小觑。而FileBasedDocument则将这两个关键点封装到了一起,让繁琐的程序文档读写操作变得简单和易维护。更简单的说,FileBasedDocument持有一个磁盘文件,执行该文件的加载与保存等逻辑操作,并可将文件中的数据转为程序内部的数据。

每一款程序内部所需的数据模型都不尽相同,即:加载(打开)磁盘文件后,如何读取,读取的结果设置给哪个或哪些数据模型,数据处理后,哪些数据写入到磁盘文件中,等等之类,都不好确定。FileBasedDocument类的做法是:将这些逻辑操作设计成纯虚函数,程序员在自己的派生类中实现之。

这就是FileBasedDocument的来龙去脉。先了解一下该类的5个纯虚函数(均为protected),这5个纯虚函数仅供派生类实现,派生类实现后,无需也不能直接调用,FileBasedDocument为这些函数另外提供了public接口。(略)

FileBasedDocument类的public成员函数:(略)

以上函数中,save…()开头的几个函数,返回值为本类的枚举常量:
 FileBasedDocument::savedOk 文件已经保存
 FileBasedDocument::userCancelledSave 用户不打算保存
 FileBasedDocument::failedToWriteToFile 写入失败

派生类继承FileBasedDocument并重写纯虚函数后,通常还需写一到多个功能性函数,执行本程序的核心操作与数据处理。这些函数所需的参数即为获取文件数据之后的数据模型对象,比如XML节点中的某个属性值。见示例代码:

FileBasedDocument类继承自ChangeBroadcaster可变消息生成类,因此,持有并使用该类对象的内容组件(或更上层的组件,比如DocumentWindow主窗口类)可继承ChangeListener可变捕获类,在changeListenerCallback()中捕获并处理FileBasedDocument所产生的消息。同时,内容组件类或更上层组件的构造函数或有关函数中,FileBasedDocument对象需addChangeListener(this)。

注意,FileBasedDocument对象无需调用基类ChangeBroadcaster的sendChangeMessage()来发送可变消息。该对象每次调用changed()均起到相同的作用。changed()函数不仅发送可变消息,还可将当前文档的状态置为“尚未保存”。