Small. Fast. Reliable.
Choose any three.
SQLite Zipfile模块

1.概述

zipfile模块提供对简单ZIP归档文件的读/写访问 。当前的实现有以下限制:

将来可能会删除部分或全部这些限制。

2.获取并编译Zipfile

主SQLite源树ext / misc / zipfile.c文件中 找到zipfile模块的代码 。可以使用以下命令将其编译为SQLite 可加载扩展

gcc -g -fPIC-共享的zipfile.c -o zipfile.so

或者,可以将zipfile.c文件编译到应用程序中。在这种情况下,应调用以下函数向每个新的数据库连接注册扩展:

int sqlite3_zipfile_init(sqlite3 * db,void *,void *);

传递的第一个参数应该是用于注册扩展名的数据库句柄。第二个和第三个参数都应传递0。

Zipfile包含在大多数命令行Shell中

3.使用Zipfile

zipfile模块提供了三个类似的界面,用于访问,更新和创建zip文件存档:

  1. 一个表值函数,提供从文件系统或内存中对现有归档的只读访问。
  2. 虚拟表,提供对存储在文件系统中的归档文件的读写访问。
  3. SQL聚合函数,可用于在内存中创建新档案。

zipfile模块提供了两个用于访问zip归档文件的类似接口。表值函数提供对现有归档的只读访问权,而虚拟表接口则提供读和写访问权。

3.1。表值函数(只读访问)

为了读取现有的zip归档文件,Zipfile模块提供了一个 表值函数,该函数接受单个参数。如果参数是文本值,则它是要从文件系统读取的zip归档文件的路径。或者,如果参数是SQL Blob,则它是zip存档数据本身。

例如,要检查当前目录中zip归档文件“ test.zip”的内容,请执行以下操作:

SELECT * FROM zipfile('test.zip');

或者,从SQLite Shell工具(readfile() 函数从文件系统读取文件的内容并将其作为Blob返回):

SELECT * FROM zipfile(readfile('test.zip'));

表值函数为zip归档中的每个记录(文件,目录或符号链接)返回一行。每行都有以下几列:

栏名内容
名称 zip文件记录的文件名/路径。
模式 UNIX模式,由stat(2)返回的zip文件记录(整数)。这标识记录的类型(文件,目录或符号链接),以及关联的用户/组/所有权限。
时光 UTC时间戳,自UNIX纪元以来的秒数(整数)。
z 解压缩后关联数据的大小(以字节为单位)(整数)。
原始数据 与zip文件条目(blob)关联的原始(可能是压缩的)数据。
数据 如果记录的压缩方法是0或8(请参见下文),则与zip文件条目关联的未压缩数据。或者,如果压缩方法不是0或8,则此列包含NULL值。
方法 用于压缩数据的压缩方法(整数)。值0表示数据未经压缩即存储在zip存档中。8表示原始放气算法。

3.2。虚拟表接口(读/写访问)

为了创建或修改现有的zip文件,必须在数据库架构中创建“ zipfile”虚拟表。CREATE VIRTUAL TABLE语句期望将zip文件的路径作为其唯一参数。例如,要写入当前目录中的压缩文件“ test.zip”,可以使用以下方法创建一个压缩文件表:

使用zipfile('test.zip')创建虚拟表temp.zip;

这样的虚拟表与上一节中描述的表值函数具有相同的列。可以使用SELECT语句以与表值函数相同的方式读取它。

使用虚拟表界面,可以通过在虚拟表中插入新行来将新条目添加到zip存档中。可以通过删除行来删除条目,也可以通过更新来修改条目。

3.2.1。将条目添加到Zip存档

可以通过插入新行将条目添加到zip存档中。最简单的方法是只为“名称”和“数据”列指定值,并用zipfile填写其他字段的明智默认值。要将目录插入存档,请将“数据”列设置为NULL。例如,要将目录“ dir1”和包含文本“ abcdefghi”的文件“ m.txt”添加到zip归档文件“ test.zip”中:

插入temp.zip(名称,数据)VALUES('dir1',NULL);           -添加目录
INSERT INTO temp.zip(name,data)VALUES('m.txt','abcdefghi');   -添加常规文件

插入目录时,如果“名称”值不以'/'字符结尾,则zipfile模块将追加一个。为了与操纵zip存档的其他程序(最著名的是“ info-zip”)兼容,这是必需的。

要插入符号链接,用户还必须提供“模式”值。例如,要将符号链接从“ link.txt”添加到“ m.txt”:

插入temp.zip(名称,模式,数据)VALUES('link.txt','lrwxrw-rw-','abcdefghi');

以下规则和警告适用于在每个INSERT语句中指定的值:

笔记
名称 必须为名称列指定非NULL文本值。如果指定的名称已经存在于归档中,这是一个错误。
模式 如果将NULL插入模式列,则新归档条目的模式将自动设置为33188(-rw-r--r--)或16877(drwxr-xr-x)。为“ sz”,“ data”和“ rawdata”列指定的值表示新条目是目录。

如果指定的值是整数(或看起来像整数的文本),则将其逐字插入。如果该值不是有效的UNIX模式,则从存档中提取文件时,某些程序可能会表现异常。

最后,如果为此列指定的值不是整数或NULL,则假定它是UNIX权限字符串,类似于“ ls -l”命令输出的字符串(例如,“-rw-r--r- -”,“ drwxr-xr-x”等)。在这种情况下,如果无法解析字符串,则为错误。
时光 如果将NULL插入到mtime列中,则新条目的时间戳记将设置为当前时间。否则,将指定的值解释为整数并按原样使用。
z 此列必须设置为NULL。如果在此列中插入了非NULL值,或者使用UPDATE语句提供了新的非NULL值,则这是一个错误。
原始数据 此列必须设置为NULL。如果在此列中插入了非NULL值,或者使用UPDATE语句提供了新的非NULL值,则这是一个错误。
数据 要将目录插入存档,必须将该字段设置为NULL。在这种情况下,如果为“模式”列明确指定了一个值,则该值必须与目录一致(即,必须为(mode&0040000)= 0040000)。

否则,插入此字段的值是常规文件的文件内容或符号链接的目标。
方法 此字段必须设置为整数值0和8之一,否则设置为NULL。

对于目录条目,插入此字段的任何值都将被忽略。否则,如果将其设置为0,则将文件数据或符号链接目标按原样存储在zip存档中,并且将压缩方法设置为0。如果将其设置为8,则使用以下命令对文件数据或链接目标进行压缩在存储压缩数据之前将其压缩,并将压缩方法设置为8。最后,如果将NULL值写入此字段,则zipfile模块会自动决定是否在存储数据之前压缩数据。

不支持在INSERT语句中为rowid字段指定一个显式值。提供的任何值都将被忽略。

3.2.2。删除Zip存档条目

通过删除相应的行,可以从现有的zip存档中删除记录。例如,使用上面创建的虚拟表从zip归档文件“ test.zip”中删除文件“ m.txt”:

从temp.zip中删除,其中name ='m.txt';

请注意,从zip归档文件中删除记录不会回收归档文件中使用的空间-只会从归档文件“中央目录结构”中删除一个条目,从而使该条目不可访问。解决这种低效率问题的一种方法是根据已编辑档案的内容创建一个新的zip档案。例如,在编辑通过虚拟表temp.zzz访问的档案后:

-创建一个新的,空的存档: 
使用zipfile('new.zip')创建虚拟表temp.newzip;

-将现有档案的内容复制到新档案中
插入temp.newzip(名称,模式,mtime,数据,方法)
    选择名称,模式,mtime,数据,方法FROM temp.zzz;

3.2.3。更新现有的Zip存档条目

可以使用UPDATE语句修改现有的zip存档条目。

zipfile虚拟表的最左三列“名称”,“模式”和“ mtime”可以分别设置为可插入同一列的任何值(请参见上文)。如果将“ mode”或“ mtime”中的任何一个设置为NULL,则根据对NULL值的INSERT所描述的确定最终值-“ mtime”的当前时间,“ mode”的33188或16877,具体取决于还是不是为zipfile表的后四列指定的值指示该条目是目录还是文件。

尝试将sz或rawdata字段设置为NULL以外的任何值都是错误的。

数据和方法列也可以按照上面针对INSERT的描述进行设置。

3.3。zipfile()聚合函数

使用zipfile()聚合函数,可以在内存中完全构建新的zip归档文件。聚合函数访问的每一行都将一个条目添加到zip存档中。返回的值是包含整个存档映像的Blob。

可以使用2、4或5个参数调用zipfile()聚合函数。如果使用5个参数调用它,则添加到存档中的条目等同于将相同的值插入zipfile虚拟表的“名称”,“模式”,“ mtime”,“数据”和“方法”列中。

如果使用2个参数调用zipfile(),则添加到存档中的条目等同于通过将相同的两个值插入zipfile虚拟表的“名称”和“数据”列中而添加的所有其他值设置为空值。如果使用4个参数调用,则等效于将这4个值插入“名称”,“模式”,“ mtime”和“数据”列中。换句话说,以下对查询是等效的:

SELECT zipfile(名称,数据)...
SELECT zipfile(名称,NULL,NULL,数据,NULL)...

SELECT zipfile(名称,模式,mtime,数据)...
SELECT zipfile(名称,模式,mtime,数据,NULL)...

例如,要创建一个包含两个文本文件“ a.txt”和“ b.txt”的档案,分别包含文本“ abc”和“ 123”:

WITH contents(名称,数据)AS(
  VALUES('a.txt','abc')UNION ALL
  VALUES('b.txt','123')
)
从目录中选择zipfile(名称,数据);