zipfile 模組提供讀/寫存取權限,可存取簡單的 ZIP 檔案。目前的實作有下列限制
這些限制中的一些或全部可能會在未來移除。
zipfile 模組的程式碼位於 ext/misc/zipfile.c 檔案中,在 SQLite 主要原始碼樹 中。它可以使用類似下列指令的命令編譯成 SQLite 可載入擴充功能
gcc -g -fPIC -shared zipfile.c -o zipfile.so
或者,zipfile.c 檔案可以編譯成應用程式。在這種情況下,應呼叫下列函數,以向每個新的資料庫連線註冊擴充功能
int sqlite3_zipfile_init(sqlite3 *db, void*, void*);
傳遞的第一個參數應該是註冊擴充功能的資料庫控制代碼。第二個和第三個參數都應該傳遞 0。
Zipfile 包含在 命令列殼層 的大多數建置中。
zipfile 模組提供三個類似的介面,用於存取、更新和建立 zip 檔案
zipfile 模組提供兩個類似的介面來存取 zip 檔案。表格值函數,提供對現有檔案的唯讀存取權限,以及虛擬表格介面,提供讀取和寫入存取權限。
對於讀取現有的 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 檔案中的每個記錄(檔案、目錄或符號連結)返回一行。每一行都有以下欄位
欄位名稱 | 內容 |
---|---|
name | zip 檔案記錄的檔案名稱/路徑。 |
mode | UNIX 模式,由 stat(2) 為 zip 檔案記錄返回(一個整數)。這會識別記錄的類型(檔案、目錄或符號連結),以及相關的使用者/群組/所有權限。 |
mtime | UTC 時間戳記,以自 UNIX 紀元以來的秒數表示(一個整數)。 |
sz | 解壓縮後相關資料的大小(以位元組為單位)(一個整數)。 |
rawdata | 與 zip 檔案條目相關的原始(可能已壓縮)資料(一個 blob)。 |
data | 如果記錄的壓縮方法是 0 或 8(見下文),則與 zip 檔案條目相關的未壓縮資料。或者,如果壓縮方法不是 0 或 8,則此欄位包含 NULL 值。 |
method | 用於壓縮資料的壓縮方法(整數)。值 0 表示資料以未壓縮的方式儲存在 zip 檔案中。8 表示原始的 deflate 演算法。 |
為了建立或修改現有的 zip 檔案,必須在資料庫結構中建立一個「zipfile」虛擬表格。CREATE VIRTUAL TABLE 陳述式預期將 zip 檔案的路徑作為其唯一引數。例如,若要寫入目前目錄中的 zip 檔案「test.zip」,可以使用下列方式建立 zipfile 表格
CREATE VIRTUAL TABLE temp.zip USING zipfile('test.zip');
此類虛擬表格具有與前一節所述的表格值函數相同的欄位。它可以透過 SELECT 陳述式讀取,方式與表格值函數相同。
使用虛擬表格介面,可以透過在虛擬表格中插入新列來將新項目新增至 zip 檔案。可以透過刪除列來移除項目,或透過更新列來修改項目。
可以透過插入新列來將項目新增至 zip 檔案。最簡單的方法是僅為「name」和「data」欄位指定值,並讓 zipfile 為其他欄位填入合理的預設值。若要將目錄插入檔案中,請將「data」欄位設定為 NULL。例如,若要將目錄「dir1」和包含文字「abcdefghi」的檔案「m.txt」新增至 zip 檔案「test.zip」
INSERT INTO temp.zip(name, data) VALUES('dir1', NULL); -- Add directory INSERT INTO temp.zip(name, data) VALUES('m.txt', 'abcdefghi'); -- Add regular file
插入目錄時,如果「name」值未以「/」字元結尾,zipfile 模組會附加一個。這是為了與處理 zip 檔案的其他程式(最著名的是「info-zip」)相容。
若要插入符號連結,使用者還必須提供「mode」值。例如,若要從「link.txt」新增符號連結至「m.txt」
INSERT INTO temp.zip(name, mode, data) VALUES('link.txt', 'lrwxrw-rw-', 'm.txt');
下列規則與注意事項適用於每個 INSERT 陳述中指定的值
欄位 | 註解 |
---|---|
name | 必須為 name 欄位指定非 NULL 文字值。如果指定的 name 已存在於檔案庫中,則會產生錯誤。 |
mode | 如果將 NULL 插入 mode 欄位,則新檔案庫條目的模式會自動設定為 33188 (-rw-r--r--) 或 16877 (drwxr-xr-x),視欄位「sz」、「data」和「rawdata」指定的值是否指出新條目為目錄而定。 如果指定的值為整數(或看起來像整數的文字),則會逐字插入。如果該值不是有效的 UNIX 模式,則某些程式在從檔案庫中擷取檔案時可能會產生異常行為。 最後,如果為此欄位指定的不是整數或 NULL,則會假設它為 UNIX 權限字串,類似於「ls -l」指令所輸出的字串(例如「-rw-r--r--」、「drwxr-xr-x」等)。在此情況下,如果無法剖析字串,則會產生錯誤。 |
mtime | 如果將 NULL 插入 mtime 欄位,則新條目的時間戳記會設定為目前時間。否則,會將指定的值詮釋為整數並照樣使用。 |
sz | 此欄位必須設定為 NULL。如果將非 NULL 值插入此欄位,或如果使用 UPDATE 陳述提供新的非 NULL 值,則會產生錯誤。 |
rawdata | 此欄位必須設定為 NULL。如果將非 NULL 值插入此欄位,或如果使用 UPDATE 陳述提供新的非 NULL 值,則會產生錯誤。 |
data |
若要將目錄插入檔案庫,此欄位必須設定為 NULL。在此情況下,如果已為「mode」欄位明確指定值,則該值必須與目錄一致(亦即,必須符合 (mode & 0040000)=0040000)。 否則,插入此欄位的值會是常規檔案的檔案內容,或符號連結的目標。 |
method |
此欄位必須設定為整數值 0 和 8 之一,或 NULL。 對於目錄項目,插入此欄位中的任何值都會被忽略。否則,如果將其設定為 0,則檔案資料或符號連結目標會儲存在 zip 檔案中,且壓縮方式設定為 0。如果將其設定為 8,則檔案資料或連結目標會在儲存前使用 deflate 壓縮,且壓縮方式設定為 8。最後,如果寫入 NULL 值到此欄位,zipfile 模組會自動決定在儲存資料前是否壓縮資料。 |
不支援在 INSERT 陳述式中指定 rowid 欄位的明確值。提供的任何值都會被忽略。
可以透過刪除對應列來從現有的 zip 檔案中移除記錄。例如,使用上面建立的虛擬表格從 zip 檔案「test.zip」中移除檔案「m.txt」
DELETE FROM temp.zip WHERE name = 'm.txt';
請注意,從 zip 檔案中刪除記錄並不會回收檔案中所使用的空間 - 它只會從檔案的「中央目錄結構」中移除一個項目,讓項目無法存取。解決此非效率問題的方法之一是根據已編輯檔案的內容建立新的 zip 檔案。例如,在編輯透過虛擬表格 temp.zzz 存取的檔案後
-- Create a new, empty, archive: CREATE VIRTUAL TABLE temp.newzip USING zipfile('new.zip'); -- Copy the contents of the existing archive into the new archive INSERT INTO temp.newzip(name, mode, mtime, data, method) SELECT name, mode, mtime, data, method FROM temp.zzz;
可以使用 UPDATE 陳述式修改現有的 zip 檔案項目。
zipfile 虛擬表格的左邊三欄「名稱」、「模式」和「修改時間」,每個都可以設定為可以插入到相同欄位中的任何值 (請見上文)。如果「模式」或「修改時間」設定為 NULL,最終值會根據 NULL 值的 INSERT 方式決定 - 「修改時間」為目前時間,「模式」為 33188 或 16877,視 zipfile 表格的後四個欄位所指定的值是否指出項目是目錄或檔案而定。
嘗試將 sz 或 rawdata 欄位設定為 NULL 以外的任何值都是錯誤的。
資料和方法欄位也可以如上文 INSERT 所述進行設定。
新的 zip 檔案可以使用 zipfile() 聚合函數完全在記憶體中建構。聚合函數拜訪的每列都會新增一個項目到 zip 檔案中。回傳的值是一個 blob,包含整個檔案映像。
zipfile() 聚合函數可以呼叫 2、4 或 5 個參數。如果呼叫 5 個參數,則新增到檔案中的項目等同於將相同的值插入到 zipfile 虛擬表格的「名稱」、「模式」、「修改時間」、「資料」和「方法」欄位中。
如果 zipfile() 呼叫 2 個參數,則新增到檔案中的項目等同於將相同的兩個值插入到 zipfile 虛擬表格的「名稱」和「資料」欄位中,所有其他值都設定為 NULL。如果呼叫 4 個參數,則等同於將 4 個值插入到「名稱」、「模式」、「修改時間」和「資料」欄位中。換句話說,以下查詢對等同
SELECT zipfile(name, data) ... SELECT zipfile(name, NULL, NULL, data, NULL) ... SELECT zipfile(name, mode, mtime, data) ... SELECT zipfile(name, mode, mtime, data, NULL) ...
例如,要建立一個包含兩個文字檔「a.txt」和「b.txt」的檔案,內容分別為「abc」和「123」
WITH contents(name, data) AS ( VALUES('a.txt', 'abc') UNION ALL VALUES('b.txt', '123') ) SELECT zipfile(name, data) FROM contents;
此頁面最後修改於 2023-06-07 13:17:51 UTC