ForestPad - 一种存储和检索文本信息的方法






3.85/5 (13投票s)
三个应用程序:PocketPC、Windows桌面和Web服务协作,以同步您的文本信息。
引言
ForestPad是一种存储和检索文本信息的方法,它由三个应用程序组成。
还包含两个安装程序项目。一个是PocketPC应用程序的安装程序,它调用自定义代码来启动ActiveSync应用程序;另一个是Windows桌面版本的安装程序。
在继续之前,我想向一个我使用了多年并决定编写替代品的出色程序致敬。这个程序是 TreePad,由 Henk Hagedoorn 编写。我还要感谢CodeProject和所有贡献者,感谢他们为.NET和C#信息方面最棒的资源之一所付出的辛勤工作。
ForestPadDesktop或ForestPadCE可以独立使用。当与ForestPadService结合使用时,它们会变得更加强大,ForestPadService允许PocketPC和桌面应用程序通过Web通信并同步数据。
目前,同步功能仅检查哪个ForestPad文档较新。这意味着如果您在两个客户端上编辑了同一个ForestPad文档,然后分别从每个客户端同步,则可能会丢失数据。相反,您必须在“断开连接”模式下工作。例如,如果您正在现场编辑PocketPC上的数据,您必须先将数据同步到ForestPadService,然后在ForestPadDesktop中编辑同一文档之前进行同步。
这种简单的方法对我来说效果很好,但也可以通过多种方式进行扩展。您可以添加一个类似于源代码管理的检入/检出系统,您可以同步节点级别的数据,或者任何适合您需求的方法。如果您一直连接到互联网,您甚至可以使同步自动化。如果您只使用其中一个客户端,您仍然可以使用ForestPadService进行备份。ForestPadService不依赖于数据库,因此您可以在支持.NET Framework的任何托管帐户上安装它。
背景
我决定编写ForestPad,以便存储所有我需要回忆的文本信息。以下是我使用它的方式:
我用它来存储歌词。在练习吉他时,我可以快速翻阅歌曲的吉他谱。(Ctrl-K) 可以将光标移到搜索框,就像 FireFox 一样,让我只需通过多次按回车键就可以快速搜索ForestPad文档中的某个项目。
我用它来存储C#代码片段。这是允许的,因为底层文件格式是带有CDATA部分的XML。目前唯一无法存储的是包含CDATA标签的XML片段。
在工作中,我存储IP地址、URL、联系人、有趣的编程文章、电子邮件地址、待办事项列表、电子邮件文本,等等。只要是文本且值得存储和检索,它都会进入ForestPad。我还将其用作便携式互联网收藏夹应用程序。要导入URL,只需将其从浏览器拖放到ForestPad桌面应用程序上。目前,链接不可点击,因为我实现了TextBox
控件而不是RichTextBox
控件。做出这个决定是因为.NET CF还没有提供RichTextBox
(尽管我了解到可以通过非托管代码访问类似的东西)。您还可以将文本从其他程序拖放到TreeView
、主TextBox
和图形按钮上。在ForestPadDesktop中,您还可以选择一段文本或整个节点,如果您已经在“设置”部分输入了SMTP服务器和“发件人”地址,则可以通过电子邮件发送文本。
ForestPad的设计决策
TreePad一直让我感到困扰的一件事并非TreePad的缺点,而是我自己的组织能力问题。我总是将信息隐藏在层级结构中太深,以至于我“丢失”了它。此外,还有一个根节点,出于某种无法解释的原因,它从图形的角度让我感到不适。我决定遵循一个严格的范例,既消除了根节点,又限制了层级结构。在每个ForestPad文档中,有多个森林,每个森林可以包含多个树、分支和叶子。我认为这种有限的层级结构也使PocketPC版本更容易使用。此外,我决定通过显示节点中第一个回车符之前的所有文本来自动命名TreeView
节点的Text
属性。这使得在PocketPC上输入更快,因为无需命名节点,并且可以轻松构建大纲而无需最小化InputPanel
。
TreePad的文件格式对我来说有些奇怪,但必须考虑到它是在1995年左右设计的。每个节点都有一个数字表示其在树中的级别,并使用以下字符串终止。
<end node> 5P9i0s8y19Z
我想 Mr. Hagedoorn 认为序列 5P9i0s8y19Z 不太可能出现在节点文本中,而且我认为这可能是正确的,因为我在使用 TreePad 的时候从来没有遇到过问题。
一个带有根节点和一个子节点的 TreePad 文件看起来像这样:
<Treepad version 2.7>
dt=Text
<node>
name
0
<end node> 5P9i0s8y19Z
dt=Text
<node>
name
1
text
<end node> 5P9i0s8y19Z
有关处理另一种文件格式的有趣代码,请查看TreePadConverter类。我包含了一个TreePad示例文件,以便您了解其工作原理。我所知道的唯一限制是,TreePad文件必须只有5个级别深度(一个根节点和四个级别),以便可以将其映射到森林、树、分支、叶子的格式。TreePad文件的根节点不会被保留。如果您以前没有使用过Stack
,并且对它的一个用途感到好奇,那么它将特别值得关注。(注意:TreePadConverter仅在“TreePad 2.7 版本”文件上进行了测试)
我希望使用XML来存储ForestPad文件,这样我就可以将数据导入其他程序,并且在用 UltraEdit 打开时,文件可以保留其视觉层级结构。
因此,与TreePad相比,ForestPad的文件格式看起来像这样:
<?xml version="1.0" encoding="utf-8"?>
<forestPad
guid="6c9325de-dfbe-4878-9d91-1a9f1a7696b0"
created="5/14/2004 1:05:10 AM"
updated="5/14/2004 1:07:41 AM">
<forest
name="A forest node"
guid="b441a196-7468-47c8-a010-7ff83429a37b"
created="01/01/2003 1:00:00 AM"
updated="5/14/2004 1:06:15 AM">
<data>
<![CDATA[A forest node
This is the text of the forest node.]]>
</data>
<tree
name="A tree node"
guid="768eae66-e9df-4999-b950-01fa9be1a5cf"
created="5/14/2004 1:05:38 AM"
updated="5/14/2004 1:06:11 AM">
<data>
<![CDATA[A tree node
This is the text of the tree node.]]>
</data>
<branch
name="A branch node"
guid="be4b0993-d4e4-4249-8aa5-fa9c940ae2be"
created="5/14/2004 1:06:00 AM"
updated="5/14/2004 1:06:24 AM">
<data>
<![CDATA[A branch node
This is the text of the branch node.]]></data>
<leaf
name="A leaf node"
guid="9c76ff4e-3ae2-450e-b1d2-232b687214aa"
created="5/14/2004 1:06:26 AM"
updated="5/14/2004 1:06:38 AM">
<data>
<![CDATA[A leaf node
This is the text of the leaf node.]]>
</data>
</leaf>
</branch>
</tree>
</forest>
</forestPad>
文档中的每个项目都包含一个Guid
、一个创建日期和一个更新日期。文本包含在“data”节点内的CDATA部分中。可以向ForestPad文件格式添加其他元素或属性,以实现更丰富的功能。
您可以通过单击其中一个图标按钮向TreeView
添加节点。ForestPad会将节点添加到当前选定项目的相对位置。节点可以在ForestPadDesktop中重新排列,但目前不能提升或降级。要删除节点,请右键单击它并选择“删除”,或者在ForestPadCE中,将触笔按住节点直到出现上下文菜单。
文档存储在两个平台上的“\My Documents\ForestPad”中。
设计目标总结
总的来说,我的设计目标是创建一个比TreePad更简单但功能相似的程序,并存在一些根本性的区别。
- 基于XML的文件格式
- 有限的节点层级
- 节点的自动命名
- 文本信息的拖放
- PocketPC和桌面版本
- 从ForestPadDesktop内部通过电子邮件发送文本片段
- 使用Web服务同步(和备份)数据
- 对不同风格用户界面的尝试
关于代码
ForestPadDesktop和ForestPadCE共享一些代码。它位于ForestPadUtilities项目中。您会注意到有几个类名为xxxxxDesktop和xxxxxCE。这些类之间的差异很小,代码本可以用编译器开关组合起来。这种方法的缺点是代码重复。优点是它使构建过程更顺畅。希望Microsoft在下一个版本中能提供对Compact Framework的明显补充,例如Guid
类。使用/unsafe指令进行编译与托管代码的概念相悖。
如果您以前没有使用过TreeView
,请查看ForestTreeNode类以及ForestDesktop.cs或ForestCE.cs中的PopulateTreeView方法,在那里您可以看到一个ForestTreeNode对象放置在附加到每个TreeView节点的Tag
中。这个Tag
包含指向XmlDocument
中相应节点的指针,并提供了一种机制来保持TreeView
和XmlDocument
的同步。
public enum ForestType
{
Forest = 0,
Tree = 1,
Branch = 2,
Leaf = 3
}
namespace ForestPadUtilities
{
/// <summary>
/// Summary description for ForestTreeNode.
/// </summary>
public class ForestTreeNode
{
public ForestType NodeType;
public string NodeName;
public XmlNode NodePointer;
public string NodeGuid;
public string NodeCreated;
public string NodeUpdated;
public ForestTreeNode()
{
}
}
}
目前,您必须下载源代码才能安装ForestPadService。稍后,我可能会构建一个安装程序。
为了完整地构建代码,您需要在“\ForestPadCE\BuildCabs\”中修改BuildCab.bat文件,以反映您的驱动器上的文件位置。简化的命令行如下:
cabwiz.exe ForestPadCE_PPC.inf /dest \ForestPad\ForestPadCE_Setup /err
Logfile.log /cpu ARMV4 ARM SH3 MIPS X86 WCE420X86
您还需要修改ForestPadCE_PPC.inf并更新路径。请阅读CodeProject文章 Developing and Deploying Pocket PC Setup Applications 以获取更多信息。
首先在Debug模式下构建,然后在Release模式下构建。我用空的文本文件替换了ForestPadCE_Setup项目中的CAB文件以节省空间。它们将在第一次Release构建期间被实际的CAB文件替换。
此解决方案需要设置一个虚拟目录。将虚拟目录指向ForestPadService目录。授予ASPNET进程对ForestPadService\DATA文件夹的完全权限。然后访问 https:///ForestPadService/Login.aspx,输入用户名:admin,密码:admin。
编辑admin用户并创建新密码。然后,在ForestPadCE或ForestPadDesktop的“设置”部分,将https:///ForestPadService/ForestPadService.asmx设置为Web服务URL,将admin作为您的用户名,并输入您新创建的密码。保存更改,创建一个文档,输入一些文本,然后选择“同步”。
您的数据将从客户端传输到ForestPadService。
安全
ForestPad目前的安全措施非常有限。在设计程序时,这不是我的主要关注点。ForestPad Web服务的密码在每个应用程序中都被加密,但目前存储在ForestPad Web服务上的数据未加密,并且密码以明文形式传输到Web服务。向事务添加加密将是一项相对简单的任务。此外,将ForestPad文档存储在数据库中或加密XML也很容易。
您还可以加密ForestPadCE和ForestPadDesktop客户端上的信息。我选择不这样做,因为我希望能够用文本编辑器打开文档。如果您存储敏感信息,我建议确保您的PocketPC和桌面计算机都设置了密码保护。就目前而言,除非您修改ForestPadService以包含加密,否则存储文档可能会使您处于风险之中。
将来,我将在 ForestPad.com 上发布一个源代码版本,可用于远程存储安全信息。
已知未解决的问题
ForestPadCE- 有时“设置”窗体而不是主窗体显示。似乎在打开和关闭“设置”窗体,然后最小化应用程序并使用“开始”菜单中的图标将其最大化后发生。
- “最近使用的程序”菜单中图标未显示的问题
- 桌面版本中奇怪的调整大小问题 - 在我的系统上,每次启动时它在垂直方向上会增长19像素。在其他系统上,行为不可预测。
- 目前,ForestPad使用“最后更新日期”进行同步。这意味着如果数据在两个位置(例如ForestPadCE / ForestPadDesktop)被编辑然后从两个位置同步,则数据可能会丢失。编辑时间最长的文件的将被覆盖。
可能的原因:
此代码可作为许多不同类型项目的 dasar(基础)。
例如:
您可以为ForestPad用户添加一个只读属性,并为办公室里的每个人设置相同的用户名和密码,以便他们都能接收您创建的ForestPad文档。您可以更进一步,允许ForestPad用户存储他们特定的用户文档,同时仍然接收只读的联合文档。或者,修改ForestPadService,将一组用户创建的所有文档直接重定向给您,作为一种数据收集机制。
在ForestPadCE中添加一个选项,将ForestPad文档存储在可移动内存卡上。
可以添加一个搜索选项,该选项可以搜索所有ForestPad文档,而不仅仅是当前打开的文档。您还可以扩展现有搜索以支持正则表达式。
您可以构建一个基于Web的ForestPad文档查看器或编辑器。
或者,您可以实现一个选项,通过IR在两个PocketPC之间传输ForestPad文档。
特别感谢
四个节点级别的图像由我的朋友Sean Kabanuk设计。
参考文献
这些资源在构建ForestPad的过程中已被证明是有用的- CodeProject
- OpenNETCF 论坛
- SourceForge
- SourceGear 慷慨地提供了SourceGear Vault的一用户免费副本