Trabajo con archivos ZIP en Swift (iOS/macOS)
En el desarrollo moderno de iOS y macOS, a menudo surge la necesidad de empaquetar y descomprimir archivos. Los archivos ZIP son el método estándar de compresión de datos, compatible en todas las plataformas de Apple. En este artículo, analizaremos las herramientas nativas de Swift para trabajar con ZIP, así como la popular biblioteca ZIPFoundation.
Herramientas nativas de Foundation
El framework Foundation proporciona capacidades básicas para trabajar con archivos a través de la clase NSFileCoordinator y utilidades del sistema. Sin embargo, para un trabajo completo con ZIP, se recomienda usar bibliotecas de terceros o envoltorios sobre comandos del sistema.
Biblioteca ZIPFoundation
ZIPFoundation es una biblioteca ligera para trabajar con archivos ZIP, escrita en Swift puro. Es compatible con iOS, macOS, tvOS y watchOS, no requiere dependencias externas y se distribuye bajo la licencia MIT.
Instalación mediante Swift Package Manager
Agregue la dependencia en Package.swift:
dependencies: [ .package(url: "https://github.com/weichsel/ZIPFoundation.git", from: "0.9.16")]O a través de Xcode: File → Add Packages → ingrese la URL del repositorio.
Operaciones principales
1. Creación de un archivo ZIP
Empaquetado de un solo archivo:
import ZIPFoundation
let fileManager = FileManager.defaultlet sourceURL = URL(fileURLWithPath: "/path/to/file.txt")let destinationURL = URL(fileURLWithPath: "/path/to/archive.zip")
do { try fileManager.zipItem(at: sourceURL, to: destinationURL) print("Archivo creado: \\(destinationURL.path)")} catch { print("Error: \\(error.localizedDescription)")}Empaquetado de un directorio completo:
let directoryURL = URL(fileURLWithPath: "/path/to/folder")let archiveURL = URL(fileURLWithPath: "/path/to/folder.zip")
do { try fileManager.zipItem(at: directoryURL, to: archiveURL) print("Directorio empaquetado")} catch { print("Error: \\(error)")}2. Descompresión de un archivo
let archiveURL = URL(fileURLWithPath: "/path/to/archive.zip")let destinationURL = URL(fileURLWithPath: "/path/to/unzip")
do { try fileManager.unzipItem(at: archiveURL, to: destinationURL) print("Descompresión completada")} catch { print("Error de descompresión: \\(error)")}3. Trabajo con el contenido del archivo sin extracción
guard let archive = Archive(url: archiveURL, accessMode: .read) else { fatalError("No se pudo abrir el archivo")}
// Lista de todas las entradasfor entry in archive { print("Archivo: \\(entry.path), tamaño: \\(entry.uncompressedSize) bytes")}
// Lectura de un archivo específicoif let entry = archive["documents/report.pdf"] { var data = Data() do { _ = try archive.extract(entry, bufferSize: 4096) { partialData in data.append(partialData) } print("Extraídos \\(data.count) bytes") } catch { print("Error: \\(error)") }}4. Adición de archivos a un archivo existente
guard let archive = Archive(url: archiveURL, accessMode: .update) else { fatalError("No se pudo abrir el archivo para actualización")}
let newFileURL = URL(fileURLWithPath: "/path/to/new_file.txt")do { try archive.addEntry(with: "new_file.txt", relativeTo: newFileURL.deletingLastPathComponent()) print("Archivo agregado")} catch { print("Error: \\(error)")}Trabajo con progreso y archivos grandes
Para archivos grandes, use Progress:
let progress = Progress(totalUnitCount: 100)let archiveURL = URL(fileURLWithPath: "/path/to/large.zip")let destinationURL = URL(fileURLWithPath: "/path/to/output")
do { try FileManager.default.unzipItem(at: archiveURL, to: destinationURL, progress