Zip

說明

建立一個 zipfile。

basedir 屬性是從中進行 zip 的參考目錄。

請注意,檔案權限不會儲存在產生的 zipfile 中。

可以調整要壓縮的檔案組。這可以使用 includesincludesfileexcludesexcludesfiledefaultexcludes 屬性來完成。使用 includesincludesfile 屬性,你可以使用樣式來指定要包含的檔案。excludeexcludesfile 屬性用於指定要排除的檔案。這也是使用樣式來完成。最後,使用 defaultexcludes 屬性,你可以指定是否要使用預設排除。請參閱 基於目錄的任務 部分,了解如何進行檔案的包含/排除,以及如何撰寫樣式。

此任務形成一個隱含的 FileSet,並支援 <fileset> 的大部分屬性(dir 變成 basedir),以及嵌套的 <include><exclude><patternset> 元素。

或者,你可以在其中放置嵌套檔案組,或檔案組的參考。在這種情況下,basedir 是可選的;隱含的檔案組僅在設定 basedir 時使用。你可以使用隱含檔案組(設定 basedir,以及可選的屬性,例如 includes 和可選的子元素,例如 <include>);明確的嵌套 <fileset> 元素,只要至少指定一個檔案組總計。ZIP 檔案將僅反映每個檔案組內部的相對路徑。Zip 任務及其衍生產品知道一種特殊形式的檔案組,稱為 zipfileset,它具有其他屬性(如下所述)。

Zip 任務還支援將多個 zip 檔案合併到 zip 檔案中。這可以透過任何嵌套檔案組的 src 屬性或使用特殊嵌套檔案組 zipgroupfileset 來完成。

update 參數控制如果 ZIP 檔案已存在會發生什麼事。設定為 yes 時,ZIP 檔案會使用指定的檔案更新。(新增新檔案;舊檔案會被新版本取代。)設定為 no(預設值)時,如果要新增到檔案庫的任何檔案都比檔案庫中的條目新,則會覆寫 ZIP 檔案。請注意,ZIP 檔案以 2 秒的精確度儲存檔案修改時間。如果檔案比檔案庫中的條目新不到 2 秒,Apache Ant 就不會將其視為較新。

當沒有檔案符合時,whenempty 參數會控制發生什麼事。如果為 skip(預設值),則不會建立 ZIP,並會發出警告。如果為 fail,則不會建立 ZIP,並會以錯誤終止建置。如果為 create,則會建立一個空的 ZIP 檔(明確地為零個項目),而符合規定的 ZIP 處理工具應可辨識為空檔。

此任務現在會對檔案名稱使用預設的 JVM 字元編碼,這與命令列 ZIP 工具一致,但如果您嘗試從 Java 內部開啟檔案,且您的檔案名稱包含非 US-ASCII 字元,就會造成問題。請使用 encoding 屬性,並將其設定為 UTF8,以建立可由 Java 安全讀取的 ZIP 檔。有關更完整的討論,請參閱下方

自 Ant 1.5.2 起<zip> 可以將 Unix 權限儲存在檔案中(請參閱 <zipfileset>filemodedirmode 屬性的說明)。遺憾的是,沒有可攜式的方式來儲存這些權限。Ant 使用 Info-Zipzipunzip 命令實作所使用的演算法,這些是許多類 Unix 系統的 zipunzip 的預設版本。

請注意,zip 格式允許多個完全限定名稱相同的文件存在於單一檔案中。這已被記錄為會對毫無戒心的使用者造成各種問題。如果您希望避免這種行為,您必須將 duplicate 屬性設定為非預設值 add

請另外注意,不同的 ZIP 工具在套用檔案的時區偏移量計算時,會以不同的方式處理時間戳記。有些 ZIP 函式庫會儲存從檔案系統讀取的時間戳記,而其他函式庫會在讀取和寫入檔案時修改時間戳記,以使所有時間戳記使用相同的時區。由一個函式庫建立的 ZIP 檔案,在由另一個函式庫解壓縮時,可能會解壓縮出具有「錯誤時間戳記」的檔案。

Ant 的 ZIP 類別使用與 InfoZIP 工具和 zlib 相同的演算法(時間戳記會調整),Windows 的「壓縮資料夾」功能和 WinZIP 都不會變更時間戳記。這表示,在 Windows 的壓縮資料夾功能所建立的檔案上使用 unzip 任務,可能會建立具有「錯誤」時間戳記的檔案,如果您使用 Windows 的功能來解壓縮 Ant 所產生的 ZIP 檔案,也會發生相同的情況。

參數

屬性 說明 必要
destfile 要建立的 zip 檔案。 兩個選項中必須擇一
zipfile 已過時 destfile 的舊名稱。
basedir 要將檔案壓縮成 zip 的目錄。
compress 不僅儲存資料,還會將資料壓縮。除非將 keepcompression 屬性設定為 false,否則這將套用於整個檔案,而不僅是更新時新增的檔案。 否;預設為 true
keepcompression 對於來自現有檔案的項目(例如嵌套的 zipfileset 或在更新檔案時),保留壓縮,如其原始狀態,而不是使用 compress 屬性。自 Ant 1.6 起 否;預設為 false
encoding 用於 zip 檔案中檔案名稱的字元編碼。有關可能值的清單,請參閱 受支援的編碼 否;預設為 JVM 預設字元編碼
filesonly 僅儲存檔案項目。 否;預設為 false
includes 必須包含的檔案模式的逗號或空格分隔清單。 否;預設為全部 (**)
includesfile 檔案名稱。此檔案的每一行都被視為包含模式。
excludes 必須排除的檔案模式的逗號或空格分隔清單。 否;預設為預設排除或如果 defaultexcludesno,則為無
excludesfile 檔案名稱。此檔案的每一行都被視為排除模式。
defaultexcludes 表示是否應使用預設排除 (yes|no)。 否;預設為 yes
update 表示如果目標檔案已存在,是否要更新或覆寫該檔案。 否;預設為 false
whenempty 當沒有檔案符合時所採取的行為。有效值為 failskipcreate 否;預設為 skip
duplicate 當找到重複檔案時所採取的行為。有效值為 addpreservefail 否;預設為 add
roundup 檔案修改時間是否會向上取整到下一偶數秒。
Zip 檔案以 2 秒為單位儲存檔案修改時間,因此時間將向上或向下取整。如果您向下取整,則在您重新執行任務時,檔案將永遠顯示為過期,因此預設為向上取整。向上取整可能會導致其他類型的問題,例如 Web 檔案中的 JSP 看起來比預編譯的頁面稍新,導致預編譯無效。自 Ant 1.6.2 起
否;預設為 true
comment 要儲存在檔案中的註解。自 Ant 1.6.3 起
層級 執行檔案壓縮時,非預設層級。有效值範圍從 0(無壓縮/最快)到 9(最大壓縮/最慢)。自 Ant 1.7 起
preserve0permissions 更新檔案或從不同檔案新增項目時,Ant 會假設 Unix 權限值 0(任何人都不被允許對檔案/目錄執行任何動作)表示權限並未儲存,而非實際權限,並會套用其自己的預設值。
如果真的想要保留原始權限欄位,請將此屬性設定為 true自 Ant 1.8.0 起
否;預設為 false
useLanguageEncodingFlag 如果編碼為 UTF-8,是否設定語言編碼旗標。如果編碼不是 UTF-8,此設定不會有任何效果。自 Ant 1.8.0 起
另請參閱以下討論
否;預設為 true
createUnicodeExtraFields 是否建立 Unicode 額外欄位,以將檔案名稱第二次儲存在項目元資料中。
可能的值為 neveralwaysnot-encodeable,後者僅在無法使用指定編碼編碼檔案名稱時新增 Unicode 額外欄位。自 Ant 1.8.0 起
另請參閱以下討論
否;預設為 never
fallbacktoUTF8 如果無法使用指定編碼編碼檔案名稱,是否使用 UTF-8 和語言編碼旗標,而不是指定編碼。自 Ant 1.8.0 起
另請參閱以下討論
否;預設為 false
zip64Mode 何時對項目使用 Zip64 延伸。可能的值為 neveralwaysas-needed自 Ant 1.9.1 起
另請參閱以下討論
否;預設為 as-needed
modificationtime 將所有儲存的檔案修改時間設定為指定時間。這可以是數字,解譯為自 1970-01-01T00:00:00Z 以來的毫秒數,或可以解析為 ISO 8601 時間戳記(包含時區)的字串。自 Ant 1.10.2 起

檔案名稱編碼

傳統上,ZIP 檔案格式使用第 437 號碼頁作為檔案名稱編碼,這對於許多國際字元集來說是不夠的。

隨著時間推移,不同的檔案壓縮器選擇了不同的方式來解決此限制,例如 java.util.zip 套件僅使用 UTF-8 作為其編碼。

Ant 提供了 zipunzip 任務的 encoding 屬性,作為明確指定要使用(或預期)的編碼的方式,自 Ant 1.4 起。它預設為 zip 的 JVM 字元編碼,以及 jar 和其他類似 jar 的任務(warear、...)以及 unzip 家族任務的 UTF-8。

較新的 ZIP 規範版本引入了稱為 語言編碼標記 的項目,可用於表示已使用 UTF-8 編碼檔案名稱。自 Ant 1.8.0 起,所有由 Ant 編寫的 zip、jar 和類似檔案都會設定此標記,如果編碼已設定為 UTF-8。我們與現有檔案編寫器的互通性測試未顯示任何不良影響(事實上,大多數檔案編寫器迄今都忽略此標記),但如果遇到問題,您可以在 zip 任務上將屬性 useLanguageEncodingFlag 設定為 false 以關閉 語言編碼標記

unzip 任務(及類似任務)會辨識語言編碼標記,如果已找到,則會忽略任務上設定的編碼。

InfoZIP 開發人員已推出新的 ZIP 額外欄位,可用於將額外的 UTF-8 編碼檔案名稱新增至條目的元資料。大多數檔案編寫器會忽略這些額外欄位。自 Ant 1.8.0 起zip 任務系列支援選項 createUnicodeExtraFields,這會讓 Ant 為所有條目(always)或僅為無法使用指定編碼編碼其名稱的條目(not-encodeable)撰寫這些額外欄位,其預設值為 never,因為額外欄位會建立較大的檔案。

zipfallbackToUTF8 屬性可用於建立檔案,這些檔案在大部分情況下使用指定的編碼,但對於無法使用指定的編碼編碼的檔案名稱,則使用 UTF-8 和語言編碼標記。

unzip 任務預設會辨識 Unicode 額外欄位,並從這些欄位讀取檔案名稱資訊,除非您將選用屬性 scanForUnicodeExtraFields 設定為 false

互通性建議

標記的最佳設定取決於您預期作為 ZIP 檔案的使用者/建立者的檔案編寫器。以下是某些測試結果,這些結果可能會被每個工具的後續版本取代。

那麼,該怎麼辦?

如果您正在建立 jar,則 java.util.zip 是您的主要使用者。我們建議您將編碼設定為 UTF-8,並保持語言編碼標記為啟用狀態。在 Java 7 之前,該標記不會對 java.util.zip 造成幫助或傷害,但支援它的封存程式會顯示正確的檔案名稱。

為了最大的互通性,最好將編碼設定為 UTF-8,啟用語言編碼標記,並在寫入 ZIP 時建立 Unicode 額外欄位。這樣的封存檔應該可以由 java.util.zip、7Zip、WinZIP、PKWARE 工具以及大多數 InfoZIP 工具正確解壓縮。不過,它們將無法與 Windows 的「壓縮資料夾」功能一起使用,而且比沒有 Unicode 額外欄位的封存檔更大。

如果 Windows 的「壓縮資料夾」是您的主要使用者,那麼您的最佳選擇是將編碼明確設定為目標平台。您可能想啟用 Unicode 額外欄位的建立,以便支援它們的工具可以正確解壓縮檔案名稱。

Zip64 延伸功能

Zip64 延伸功能提供一種方式,可以建立大於 4 GB 或包含超過 65535 個條目的封存檔,或使用 ZIP 延伸欄位機制新增大於 4 GB 的個別條目。這些延伸功能受到大多數現代 ZIP 實作的支援。

當 Ant 將壓縮條目寫入它建立的封存檔時,它在寫入條目之前不知道條目的壓縮大小。不幸的是,是否要寫入 Zip64 額外欄位的決定必須在寫入條目的內容之前做出。

Ant 1.9.0 引入了對 Zip64 延伸功能的支援,但沒有提供對它們的使用進行任何控制。自 Ant 1.9.1 起,已將新的 zip64mode 屬性新增到 zip 任務系列。它支援三個值

依需要 提供一個折衷方案,如果你不知道你的檔案是否會超過傳統 zip 檔案的限制,但又不想浪費太多空間(Zip64 擴充套件會佔用額外的空間)。不幸的是,有些 ZIP 實作不了解 Zip64 額外欄位,或無法解析在中央目錄中不存在的本地檔案標頭中的額外欄位的檔案,其中一個這樣的實作是 Java 5 的 java.util.zip 套件,這就是為什麼 jar 任務預設為 從不。使用 依需要 建立的檔案可以用 Java 6 和更新版本毫無問題地讀取。

指定為巢狀元素的參數

任何資源集合

資源集合 用於選擇要封存的檔案群組。

在 Ant 1.7 之前,只有 <fileset><zipfileset> 已被支援為巢狀元素。

zipgroupfileset

<zipgroupfileset> 允許將多個 zip 檔案合併到檔案中。在此檔案集中找到的每個檔案都會以 zipfileset src 檔案新增的方式新增到檔案中。

<zipgroupfileset>檔案集,並支援其所有屬性和巢狀元素。

範例

htdocs/manual 目錄中的所有檔案壓縮到 ${dist} 目錄中名為 manual.zip 的檔案中。

<zip destfile="${dist}/manual.zip"
     basedir="htdocs/manual"/>

htdocs/manual 目錄中的所有檔案壓縮到 ${dist} 目錄中名為 manual.zip 的檔案中。如果 manual.zip 不存在,則建立它;否則,使用新的/已變更的檔案更新它。

<zip destfile="${dist}/manual.zip"
     basedir="htdocs/manual"
     update="true"/>

壓縮 htdocs/manual 目錄中的所有檔案。目錄 mydocs 中的檔案或名稱為 todo.html 的檔案會被排除。

<zip destfile="${dist}/manual.zip"
     basedir="htdocs/manual"
     excludes="mydocs/**, **/todo.html"/>

壓縮 htdocs/manual 目錄中的所有檔案。只有目錄 api 下的 html 檔案會被壓縮,而名稱為 todo.html 的檔案會被排除。

<zip destfile="${dist}/manual.zip"
     basedir="htdocs/manual"
     includes="api/**/*.html"
     excludes="**/todo.html"/>

壓縮 htdocs/manual 目錄中的所有檔案,並將目前目錄中的檔案 ChangeLog.txt 也新增進去。ChangeLog.txt 將會被新增到 ZIP 檔案的最上方,就像它位於 htdocs/manual/ChangeLog.txt 一樣。

<zip destfile="${dist}/manual.zip">
  <fileset dir="htdocs/manual"/>
  <fileset dir="." includes="ChangeLog.txt"/>
</zip>

htdocs/manual 目錄中的所有檔案壓縮到檔案中的 docs/user-guide 目錄,將目前目錄中的 ChangeLog27.txt 檔案新增為 docs/ChangeLog.txt,並將 examples.zip 中的所有 html 檔案包含在 docs/examples 中。

<zip destfile="${dist}/manual.zip">
  <zipfileset dir="htdocs/manual" prefix="docs/user-guide"/>
  <zipfileset dir="." includes="ChangeLog27.txt" fullpath="docs/ChangeLog.txt"/>
  <zipfileset src="examples.zip" includes="**/*.html" prefix="docs/examples"/>
</zip>

檔案可能會包含以下檔案

    docs/user-guide/html/index.html
    docs/ChangeLog.txt
    docs/examples/index.html

htdocs/manual 目錄中的所有檔案壓縮到檔案中的 docs/user-guide 目錄,並包含符合 examples*.zip 的任何檔案中的所有檔案,例如 examples1.zipexamples_for_brian.zip 中的所有檔案。

<zip destfile="${dist}/manual.zip">
  <zipfileset dir="htdocs/manual" prefix="docs/user-guide"/>
  <zipgroupfileset dir="." includes="examples*.zip"/>
</zip>

可以使用以下方式達成相同目的

<zip destfile="${dist}/manual.zip">
  <mappedresources>
    <fileset dir="htdocs/manual"/>
    <globmapper from="*" to="docs/user-guide/*"/>
  </mappedresources>
  <archives>
    <zips>
      <fileset dir="." includes="examples*.zip"/>
    </zips>
  </archives>
</zip>

將 TAR 檔案重新打包為 ZIP 檔案。如果 Unix 檔案權限已儲存在 TAR 檔案中的一部分,它們將保留在產生的 ZIP 檔案中。

<zip destfile="release.zip">
  <tarfileset src="release.tar"/>
</zip>