【问题标题】:Creating a ZIP file from a string in Swift在 Swift 中从字符串创建 ZIP 文件
【发布时间】:2018-03-30 13:27:41
【问题描述】:
 let data = "InPractiseThisWillBeAReheallyLongString"
     
        createDir()
        
        let docsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let ourDir = docsDir.appendingPathComponent("ourCustomDir/")
        let tempDir = ourDir.appendingPathComponent("temp/")
        let unzippedDir = tempDir.appendingPathComponent("unzippedDir/")
        let unzippedfileDir = unzippedDir.appendingPathComponent("unZipped.txt")
        let zippedDir = tempDir.appendingPathComponent("Zipped.zip")
        do {
            
            try data.write(to: unzippedfileDir, atomically: false, encoding: .utf8)
            
            
            let x = SSZipArchive.createZipFile(atPath: zippedDir.path, withContentsOfDirectory: unzippedfileDir.path)
            
            var zipData: NSData! = NSData()
            
            do {
                zipData = try NSData(contentsOfFile: unzippedfileDir.path, options: NSData.ReadingOptions.mappedIfSafe)
                //once I get a readable .zip file, I will be using this zipData in a multipart webservice
            }
            catch let err as NSError {
                print("err 1 here is :\(err.localizedDescription)")
            }
        }
        catch let err as NSError {
            
            print("err 3 here is :\(err.localizedDescription)")
        }

createDir函数是:

func createDir() {
        let docsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let ourDir = docsDir.appendingPathComponent("ourCustomDir/")
        let tempDir = ourDir.appendingPathComponent("temp/")
        let unzippedDir = tempDir.appendingPathComponent("unzippedDir/")
        let fileManager = FileManager.default
        if fileManager.fileExists(atPath: tempDir.path) {
            deleteFile(path: tempDir)
            deleteFile(path: unzippedDir)
        } else {
            print("file does not exist")
            do {
                try FileManager.default.createDirectory(atPath: tempDir.path, withIntermediateDirectories: true, attributes: nil)
                try FileManager.default.createDirectory(atPath: unzippedDir.path, withIntermediateDirectories: true, attributes: nil)
                print("creating dir \(tempDir)")
            } catch let error as NSError {
                print("here : " + error.localizedDescription)
            }
        }
    }

现在我没有收到任何错误,但是当我下载我的 appData 容器,获取 ZIP 文件并尝试解压缩时,我告诉 ZIP 文件是空的。我可以看到 unzipped.text 文件确实按预期存在。

知道我做错了什么吗?

有没有一种方法可以直接从字符串创建.zip,而不必将文件保存到数据容器中?


更新

我还尝试了以下方法,结果完全相同:

let zipArch = SSZipArchive(path: zippedDir.path)
        print(zipArch.open)
        print(zipArch.write(dataStr.data(using: String.Encoding.utf8)!, filename: "blah.txt", withPassword: ""))
        print(zipArch.close)

【问题讨论】:

  • zipArch.write(dataStr.data(using: String.Encoding.utf8)!, filename: "blah.txt", withPassword: nil) 是您正在寻找的。您使用的是最新版本的 SSZipArchive 吗?您可能想向github.com/ZipArchive/ZipArchive/issues提出错误请求

标签: ios swift zip nsfilemanager ssziparchive


【解决方案1】:

小提示:您可以在不使用第三方库的情况下压缩任何内容;)

/// Zip the itemAtURL (file or folder) into the destinationFolderURL with the given zipName
/// - Parameters:
///   - itemURL: File or folder to zip
///   - destinationFolderURL: destination folder
///   - zipName: zip file name
/// - Throws: Error in case of failure in generating or moving the zip
func zip(itemAtURL itemURL: URL, in destinationFolderURL: URL, zipName: String) throws {
    var error: NSError?
    var internalError: NSError?
    NSFileCoordinator().coordinate(readingItemAt: itemURL, options: [.forUploading], error: &error) { (zipUrl) in
        // zipUrl points to the zip file created by the coordinator
        // zipUrl is valid only until the end of this block, so we move the file to a temporary folder
        let finalUrl = destinationFolderURL.appendingPathComponent(zipName)
        do {
            try FileManager.default.moveItem(at: zipUrl, to: finalUrl)
        } catch let localError {
            internalError = localError as NSError
        }
    }
    
    if let error = error {
        throw error
    }
    if let internalError = internalError {
        throw internalError
    }
}

【讨论】:

    【解决方案2】:

    我用 ZipFoundation 做到了 --> https://github.com/weichsel/ZIPFoundation

    斯威夫特

    100% 工作!!

    1) 将 ZipFoundation 框架添加到您的项目中

    2) 将导入添加到您的类

       import ZIPFoundation //Add to top of your class
    

    调用函数

         zipString() . // Do your work
         extract(fileName: "myZip.zip") //Extract it to test it
         read(fileName : "zipTxt.txt" )  //Read you extracted File
    

    为你的类添加函数

    func zipString() {
    
        let zipName = "myZip.zip"
        let myTxtName = "zipTxt.txt"
        let myString = "I love to zip files"  // In your case "InPractiseThisWillBeAReheallyLongString"
    
        if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
            let fileURL = dir.appendingPathComponent(zipName)
    
            //Create the zip file
            guard let archive = Archive(url: fileURL, accessMode: .create) else  {
                return
            }
    
           /* guard let archive = Archive(url: fileURL, accessMode: .update) else  {
                return
            } */ // In case you want to update
    
            print("CREATED")
    
             //Add file to
            let data = myString.data(using: .utf8)
            try? archive.addEntry(with: myTxtName, type: .file, uncompressedSize: UInt32(data!.count), compressionMethod: .deflate, provider: { (position, size) -> Data in
    
                return data!
            })
    
             print("ADDED")
        }
    
    }
    

    奖励文件提取

        /**
     ** Extract file for a given name
     **/
    func extract(fileName : String){
    
        let fileManager = FileManager()
        let file = fileName
        // let currentWorkingPath = fileManager.currentDirectoryPath
        if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
    
            let fileURL = dir.appendingPathComponent(file)
            do {
                // try fileManager.createDirectory(at: dir, withIntermediateDirectories: true, attributes: nil)
                try fileManager.unzipItem(at: fileURL, to: dir)
                print("EXTRACTED")
    
            } catch {
                print("Extraction of ZIP archive failed with error:\(error)")
            }
    
        }
    
    }
    

    用于测试您提取的文件

          func read(fileName : String){
        let file = fileName //this is the file. we will write to and read from it
    
        if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
    
            let fileURL = dir.appendingPathComponent(file)
    
            //reading
            do {
                let text2 = try String(contentsOf: fileURL, encoding: .utf8)
                print(text2)
            }
            catch {/* error handling here */}
        }
    }
    

    我的控制台输出...

    创建

    添加

    提取

    我喜欢压缩文件

    【讨论】:

    • 它在压缩单个文件时工作。遗憾的是,在将整个目录作为 URL 传递时,它会创建一个无法提取的损坏的 .zip 文件。
    【解决方案3】:

    您可以使用ZIPFoundation,这是另一个 Swift ZIP 库,可让您读取、创建和修改 ZIP 文件。它的优点之一是它允许您“即时”添加 ZIP 条目。在从它创建存档之前,您不必将字符串写入磁盘。它提供了一个基于闭包的 API,您可以在其中将字符串直接输入到新创建的存档中:

    func zipString() {
        let string = "InPractiseThisWillBeAReheallyLongString"
        var archiveURL = URL(fileURLWithPath: NSTemporaryDirectory())
        archiveURL.appendPathComponent(ProcessInfo.processInfo.globallyUniqueString)
        archiveURL.appendPathExtension("zip")
        guard let data = string.data(using: .utf8) else { return }
        guard let archive = Archive(url: archiveURL, accessMode: .create) else { return }
    
        try? archive.addEntry(with: "unZipped.txt", type: .file, uncompressedSize: UInt32(data.count), provider: { (position, size) -> Data in
            return data
        })
    }
    

    addEntry 方法还有一个可选的bufferSize 参数,可用于执行分块加法(这样您就不必将整个数据对象加载到 RAM 中。)

    【讨论】:

    • 是否支持多文件zip?谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多