小. 快速. 可靠.
选择任意三个.
SQLite Archive Files

1. Introduction

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

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

CREATE TABLE sqlar(
  name TEXT PRIMARY KEY,  -- name of the file
  mode INT,               -- access permissions
  mtime INT,              -- last modification time
  sz INT,                 -- original file size
  data BLOB               -- compressed content
);

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

1.1. Database As Container Object

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

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

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

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

1.2. Applications Using SQLite Archives

Fossil分布式版本控制系统为用户提供了以Tarball,ZIP存档或SQLite存档下载签入的选项.

2. Advantages Of SQLite Archives

  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. Disadvantages Of SQLite Archives

  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
    Tarball 9,781,109
  3. SQLite存档仅支持Deflate压缩方法. Tarball和ZIP Archive支持更广泛的压缩方法.

4. Managing An SQLite Archive From The Command-Line

创建,更新,列出和提取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 -At
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. Other command-line tools

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

5. Managing SQLite Archives From Application Code

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

sqlar_compress(X)

sqlar_compress(X)函数尝试使用Default算法压缩字符串或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存档中:

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

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

SELECT name, mode, datetime(mtime,'unixepoch'), sqlar_uncompress(data,sz)
  FROM sqlar
 WHERE ...;

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

by  ICOPY.SITE