“ SQLite存档”是类似于ZIP存档或 Tarball的文件容器, 但基于SQLite数据库。
SQLite存档是普通的SQLite数据库文件,其中包含下表作为其架构的一部分:
创建表sqlar( 名称TEXT PRIMARY KEY,-文件名 INT模式-访问权限 mtime INT,-上次修改时间 sz INT,-原始文件大小 数据BLOB-压缩内容 );
SQLAR表的每一行都保存单个文件的内容。文件名(相对于归档根目录的完整路径名)在“名称”字段中。“模式”字段是一个整数,它是文件的Unix风格的访问权限。“ mtime”是文件自1970年以来的修改时间,以秒为单位。“ sz”是文件的原始未压缩大小。“数据”字段包含文件内容。内容通常使用Deflate压缩,尽管并非总是如此。如果“ sz”字段等于“ data”字段的大小,则内容将以未压缩的方式存储。
SQLite存档是一个更普遍的想法的示例,该想法认为SQLite数据库可以充当包含许多较小数据组件的容器对象。
对于像PostgreSQL或Oracle这样的客户端/服务器数据库,用户和开发人员倾向于将数据库视为服务或“节点”,而不是对象。这是因为数据库内容分布在服务器上的多个文件中,或者可能分布在服务群集中的多个服务器上。一个人不能指向一个文件甚至一个目录,都不能说“这就是数据库”。
相反,SQLite将所有内容存储在磁盘上的单个文件中。您可以指向该文件,然后说“这是数据库”。它表现为一个对象。SQLite数据库文件可以被复制,重命名,作为电子邮件附件发送,作为POST HTTP请求的参数传递,或者被视为其他数据对象,例如图像,文档或媒体文件。
研究表明,许多应用程序已经使用SQLite作为容器对象。例如, Kennedy (与SQLite开发人员无关)报告说,有14%的Android应用程序从未写入其SQLite数据库。据信,这些应用程序正在从云下载整个数据库,然后根据需要在本地使用信息。换句话说,应用程序使用SQLite的不仅仅是数据库,而是可查询的电汇格式。
该化石分布式版本控制系统为用户提供了选择下载签入的任何压缩包,ZIP档案,或SQLite的档案。
SQLite存档非常灵活。ZIP存档和Tarball仅限于仅存储文件。SQLite存档存储文件以及其他对应用程序有用的表格和/或关系数据。
SQLite存档是事务性的。即使更新过程中发生崩溃或断电,更新也是原子的且持久的。读者会看到内容的一致且不变的版本,即使其他一些过程正在同时更新归档文件也是如此。
SQLite存档可以增量更新。可以添加或删除或替换单个文件,而无需重写整个存档。
可以使用高级查询语言(SQL)来查询SQLite存档。一些例子:
已经将SQLite用于其他目的的应用程序可以使用一个小的扩展名(https://sqlite.org/src/file/ext/misc/sqlar.c)轻松添加对SQLite Archives的支持,以处理内容的压缩和解压缩。如果归档文件中的文件未压缩,则即使是很小的扩展名也可以忽略。相比之下,支持ZIP存档和/或Tarball则需要单独的库或大量额外的自定义代码,或者有时两者都需要。
SQLite存档可以解决防火墙强加的检查问题。例如,某些被认为是“危险”的文件类型(例如:DLL)将被 Gmail阻止 ,甚至可能被许多其他电子邮件服务和防火墙阻止,即使这些文件被包装在ZIP存档或Tarball中也是如此。但是这些防火墙通常(至今)还不了解SQLite存档,因此可以将内容放入SQLite存档中以逃避审查。
SQLite存档是一种相对较新的格式。最早在2014年进行了描述。另一方面,ZIP存档和Tarball已有数十年的历史了,并已牢固地确立为标准格式。大多数程序员都知道ZIP存档或Tarball是什么,但是如果您说“ SQLite存档”,则更有可能收到“什么?”的答复。用于处理ZIP存档和Tarball的工具更可能安装在库存计算机上。
由于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存档(使用zipfile) | 10,390,215 |
塔球 | 9,781,109 |
SQLite存档仅支持Deflate压缩方法。Tarballs和ZIP Archive支持更广泛的压缩方法。
建议的创建,更新,列出和提取SQLite存档的方法是将sqlite3.exe命令行外壳 用于SQLite 3.23.0(2018-04-02)或更高版本。此CLI支持-A命令行选项,该选项可轻松管理SQLite存档。用于SQLite版本3.22.0(2018-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数据库,则所有这些命令都以相同的方式工作。
就像有用于管理ZIP存档的“ zip”程序和用于管理Tarball的“ tar”程序一样,也存在用于管理SQL存档的 “ sqlar”程序。“ sqlar”程序能够创建新的SQLite存档,列出现有存档的内容,从存档中添加或删除文件和/或从存档中提取文件。一个单独的“ sqlarfs”程序能够将SQLite存档作为Fuse文件系统挂载。
通过链接到SQLite并包括ext / misc / sqlar.c扩展来处理压缩和解压缩,应用程序可以轻松地读取或写入SQLite存档 。sqlar.c扩展创建了两个新的SQL函数。
sqlar_compress(X)函数尝试使用默认算法压缩字符串或Blob X的副本,并将结果作为Blob返回。如果输入X是不可压缩的,则返回X的副本。在将内容插入SQLite存档时使用此例程。
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扩展名。