Small. Fast. Reliable.
Choose any three.
SQLite存档文件

1.简介

“ SQLite存档”是类似于ZIP存档Tarball的文件容器, 但基于SQLite数据库。

SQLite存档是普通的SQLite数据库文件,其中包含下表作为其架构的一部分:

创建表sqlar(
  名称TEXT PRIMARY KEY,-文件名
  INT模式-访问权限
  mtime INT,-上次修改时间
  sz INT,-原始文件大小
  数据BLOB-压缩内容
);

SQLAR表的每一行都保存单个文件的内容。文件名(相对于归档根目录的完整路径名)在“名称”字段中。“模式”字段是一个整数,它是文件的Unix风格的访问权限。“ mtime”是文件自1970年以来的修改时间,以秒为单位。“ sz”是文件的原始未压缩大小。“数据”字段包含文件内容。内容通常使用Deflate压缩,尽管并非总是如此。如果“ sz”字段等于“ data”字段的大小,则内容将以未压缩的方式存储。

1.1。数据库作为容器对象

SQLite存档是一个更普遍的想法的示例,该想法认为SQLite数据库可以充当包含许多较小数据组件的容器对象。

对于像PostgreSQL或Oracle这样的客户端/服务器数据库,用户和开发人员倾向于将数据库视为服务或“节点”,而不是对象。这是因为数据库内容分布在服务器上的多个文件中,或者可能分布在服务群集中的多个服务器上。一个人不能指向一个文件甚至一个目录,都不能说“这就是数据库”。

相反,SQLite将所有内容存储在磁盘上单个文件中。您可以指向该文件,然后说“这是数据库”。它表现为一个对象。SQLite数据库文件可以被复制,重命名,作为电子邮件附件发送,作为POST HTTP请求的参数传递,或者被视为其他数据对象,例如图像,文档或媒体文件。

研究表明,许多应用程序已经使用SQLite作为容器对象。例如, Kennedy (与SQLite开发人员无关)报告说,有14%的Android应用程序从未写入其SQLite数据库。据信,这些应用程序正在从云下载整个数据库,然后根据需要在本地使用信息。换句话说,应用程序使用SQLite的不仅仅是数据库,而是可查询的电汇格式。

1.2。使用SQLite存档的应用程序

化石分布式版本控制系统为用户提供了选择下载签入的任何压缩包,ZIP档案,或SQLite的档案。

2. SQLite存档的优势

  1. SQLite存档非常灵活。ZIP存档和Tarball仅限于仅存储文件。SQLite存档存储文件以及其他对应用程序有用的表格和/或关系数据。

  2. SQLite存档是事务性的。即使更新过程中发生崩溃或断电,更新也是原子的且持久的。读者会看到内容的一致且不变的版本,即使其他一些过程正在同时更新归档文件也是如此。

  3. SQLite存档可以增量更新。可以添加或删除或替换单个文件,而无需重写整个存档。

  4. 可以使用高级查询语言(SQL)来查询SQLite存档。一些例子:

    • 归档文件中名称以“ .h”或“ .cpp”结尾的所有文件的总大小是多少?
    • 百分之几的文件压缩率不到25%?
    • 存档中有多少个可执行文件?
    诸如此类(以及无数其他)的问题都可以得到解答,而无需解压缩或提取任何内容。
  5. 已经将SQLite用于其他目的的应用程序可以使用一个小的扩展名(https://sqlite.org/src/file/ext/misc/sqlar.c)轻松添加对SQLite Archives的支持,以处理内容的压缩和解压缩。如果归档文件中的文件未压缩,则即使是很小的扩展名也可以忽略。相比之下,支持ZIP存档和/或Tarball则需要单独的库或大量额外的自定义代码,或者有时两者都需要。

  6. SQLite存档可以解决防火墙强加的检查问题。例如,某些被认为是“危险”的文件类型(例如:DLL)将被 Gmail阻止 ,甚至可能被许多其他电子邮件服务和防火墙阻止,即使这些文件被包装在ZIP存档或Tarball中也是如此。但是这些防火墙通常(至今)还不了解SQLite存档,因此可以将内容放入SQLite存档中以逃避审查。

3. SQLite存档的缺点

  1. SQLite存档是一种相对较新的格式。最早在2014年进行了描述。另一方面,ZIP存档和Tarball已有数十年的历史了,并已牢固地确立为标准格式。大多数程序员都知道ZIP存档或Tarball是什么,但是如果您说“ SQLite存档”,则更有可能收到“什么?”的答复。用于处理ZIP存档和Tarball的工具更可能安装在库存计算机上。

  2. 由于SQLite数据库是一种更通用的格式(其功能不只是存储一堆文件而已,所以它的功能不如ZIP存档或Tarball格式那么紧凑。SQLite存档通常比等效的ZIP存档大大约1%。Tarball被压缩为一个单元,而不是像SQLite和ZIP存档一样分别压缩每个文件。由于这些原因,Tarball往往小于ZIP或SQLite存档。

    例如,下表显示了SQLite 3.22.0源代码树中的1,743个文件的SQLite存档,ZIP存档和Tarball的相对大小:

    SQLite档案10,754,048
    ZIP存档(使用Info-ZIP 3.0)10,662,365
    ZIP存档(使用zipfile10,390,215
    塔球 9,781,109
  3. SQLite存档仅支持Deflate压缩方法。Tarballs和ZIP Archive支持更广泛的压缩方法。

4.从命令行管理SQLite存档

建议的创建,更新,列出和提取SQLite存档的方法是将sqlite3.exe命令行外壳 用于SQLite 3.23.02018-04-02)或更高版本。此CLI支持-A命令行选项,该选项可轻松管理SQLite存档。用于SQLite版本3.22.02018-01-22)的CLI具有用于管理SQLite存档的 .archive命令,但是需要与Shell进行交互。

要使用以下命令之一列出名为“ example.sqlar”的SQLite存档中的所有文件:

sqlite3 example.sqlar-在
sqlite3 example.sqlar -Atv

要从名为“ example.sqlar”的SQLite存档中提取所有文件,请执行以下操作:

sqlite3 example.sqlar -Ax

要创建一个新的名为“ alltxt.sqlar”的SQLite存档,其中包含当前目录中的所有* .txt文件:

sqlite3 alltxt.sqlar -Ac * .txt

要在现有SQLite存档中添加或更新文件,请执行以下操作:

sqlite3 example.sqlar -Au * .md

有关用法提示和所有选项的摘要,只需为CLI提供 -A选项即可,不带其他参数:

sqlite3 -A

如果filename参数是ZIP存档而不是SQLite数据库,则所有这些命令都以相同的方式工作。

4.1。其他命令行工具

就像有用于管理ZIP存档的“ zip”程序和用于管理Tarball的“ tar”程序一样,也存在用于管理SQL存档的 “ sqlar”程序。“ sqlar”程序能够创建新的SQLite存档,列出现有存档的内容,从存档中添加或删除文件和/或从存档中提取文件。一个单独的“ sqlarfs”程序能够将SQLite存档作为Fuse文件系统挂载。

5.从应用程序代码管理SQLite存档

通过链接到SQLite并包括ext / misc / sqlar.c扩展来处理压缩和解压缩,应用程序可以轻松地读取或写入SQLite存档 。sqlar.c扩展创建了两个新的SQL函数。

sqlar_compress(X)

sqlar_compress(X)函数尝试使用默认算法压缩字符串或Blob X的副本,并将结果作为Blob返回。如果输入X是不可压缩的,则返回X的副本。在将内容插入SQLite存档时使用此例程。

sqlar_uncompress(Y,SZ)

sqlar_uncompress(Y,SZ)函数将撤消sqlar_compress(X)完成的压缩。Y参数是压缩的内容(先前调用sqlar_compress()的输出),SZ是生成Y的输入X的原始未压缩大小。如果SZ小于或等于Y的大小,则表明没有压缩发生,因此sqlar_uncompress(Y,SZ)返回Y的副本。否则,sqlar_uncompress(Y,SZ)在Y上运行Inflate算法以对其进行解压缩并将其恢复为原始形式并返回未压缩的内容。从SQLite存档中提取内容时使用此例程。

使用上述两个例程,应用程序可以很容易地将新记录插入SQLite存档或从中提取现有记录。使用如下代码将新的插入到SQLite存档中:

插入sqlar(name,mode,mtime,sz,data)
 VALUES($ name,$ mode,strftime('%s',$ mtime),
         length($ content),sqlar_compress($ content));

使用以下代码从SQLite存档中提取条目:

选择名称,模式,日期时间(mtime,'unixepoch'),sqlar_uncompress(data,sz)
  从sqlar
 在哪里 ...;

上面的代码适用于一般情况。对于仅存储未压缩或不可压缩内容的SQLite存档的特殊情况(例如,在仅存储JPEG,GIF和/或PNG图像的SQLite存档中可能会出现这种情况),则可以将内容插入并提取无需使用sqlar_compress()和sqlar_uncompress()函数即可从数据库中获取数据,并且不需要sqlar.c扩展名。