ios - CSV 格式不正确

标签 ios swift csv

我正在保存 CSV 文件并通过电子邮件发送。它可以工作,但 CSV 格式不正确。一些应移至新行的项目包含在现有行的第二列中。有5列,id,name,model,ups,price。创建文件时我做错了什么吗?

func openActions() {
        actions = UIAlertController(title: "", message: "", preferredStyle: .ActionSheet)
        let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: {
            (action) -> Void in
            self.actions?.dismissViewControllerAnimated(true, completion: nil)
        })

        let saveCSV = UIAlertAction(title: "Save as CSV", style: .Default, handler: {
            (action) -> Void in
            self.getAndSaveItems()
            self.actions?.dismissViewControllerAnimated(true, completion: nil)
        })

        let viewFile = UIAlertAction(title: "View CSV", style: .Default, handler: {
            (action) -> Void in
            self.viewFile()
            self.actions?.dismissViewControllerAnimated(true, completion: nil)
        })

        let emailFile = UIAlertAction(title: "Email CSV", style: .Default, handler: {
            (action) -> Void in
            self.emailFile()
            self.actions?.dismissViewControllerAnimated(true, completion: nil)
        })

        actions?.addAction(cancelAction)
        actions?.addAction(emailFile)
        actions?.addAction(viewFile)
        actions?.addAction(saveCSV)
        self.presentViewController(actions!, animated: true, completion: nil)
    }

    func dataFilePath() -> String {
        let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
        let documentsDirectory = paths[0]
        let titleString = self.title!.stringByReplacingOccurrencesOfString(" ", withString: "_")
        let string = String(format: "/%@.csv", titleString)
        return documentsDirectory.stringByAppendingString(string)
    }

    func getAndSaveItems() {
        let getLimit = 1000
        var getSkip = 0

        activityIndicator?.startAnimating()

        let query = PFQuery(className: "Items")
        query.whereKey("user", equalTo: PFUser.currentUser()!)
        query.whereKey("collection", equalTo: self.title!)
        query.orderByAscending("item")
        query.limit = getLimit
        query.skip = getSkip
        query.findObjectsInBackgroundWithBlock( {
            (objects, error) -> Void in
            if error == nil {
                if let objects = objects as [PFObject]! {
                    for object in objects {
                        self.names.append(object["item"] as! String)
                        self.upcs.append(object["upc"] as! String)
                        self.ids.append(object.objectId!)
                        self.models.append(object["model"] as! String)
                        self.prices.append(object["pricePaid"] as! String)
                        if object["notes"] == nil {
                            self.notes.append(nil)
                        } else {
                            self.notes.append(object["notes"] as? String)
                        }
                    }
                }

                if objects!.count == getLimit {
                    getSkip += getLimit
                    self.getAndSaveItems()
                }
            } else {
                // Show error...
            }
        })

        writeToFile()
    }

    func writeToFile() {
        if (!NSFileManager.defaultManager().fileExistsAtPath(self.dataFilePath())) {
            NSFileManager.defaultManager().createFileAtPath(self.dataFilePath(), contents: nil, attributes: nil)
        }

        // var writeString = NSMutableString(capacity: 0)
        var writeString = String()
        writeString.reserveCapacity(0)

        for (var i = 0; i < names.count; i++) {
            let stringToWrite = String(format: "%@,%@,%@,%@,%@, \n", ids[i], names[i], models[i], upcs[i], prices[i])
            writeString.appendContentsOf(stringToWrite)
        }

        let handle = NSFileHandle(forWritingAtPath: self.dataFilePath())
        handle?.truncateFileAtOffset((handle?.seekToEndOfFile())!)
        handle?.writeData(writeString.dataUsingEncoding(NSUTF8StringEncoding)!)

        self.activityIndicator?.stopAnimating()
    }

    func viewFile() {
        if (NSFileManager.defaultManager().fileExistsAtPath(dataFilePath())) {
            let fileData = NSData(contentsOfFile: dataFilePath())

            let fileVC = FileViewController(nibName: "FileViewController", bundle: nil)
            let navController = NavController(rootViewController: fileVC)
            fileVC.fileData = fileData
            self.presentViewController(navController, animated: true, completion: nil)
        } else {
            // File doesn't exist...
            print("File doesn't exist")
        }
    }

    func emailFile() {
        if (NSFileManager.defaultManager().fileExistsAtPath(dataFilePath())) {
            if MFMailComposeViewController.canSendMail() {
                let mailComposer = MFMailComposeViewController()
                mailComposer.mailComposeDelegate = self
                let subject = String(format: "My %@ Collection", self.title!)
                mailComposer.setSubject(subject)
                mailComposer.setMessageBody("", isHTML: false)

                let fileData = NSData(contentsOfFile: dataFilePath())
                let titleString = self.title!.stringByReplacingOccurrencesOfString(" ", withString: "_")
                let fileNameString = String(format: "%@.csv", titleString)
                mailComposer.addAttachmentData(fileData!, mimeType: "text/csv", fileName: fileNameString)

                self.presentViewController(mailComposer, animated: true, completion: nil)
            } else {
                // Can't send mail...
            }
        } else {
            // File doesn't exist...
            print("File doesn't exist")
        }
    }

    func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?) {
        self.dismissViewControllerAnimated(true, completion: nil)
    }

enter image description here

最佳答案

这一行:

let stringToWrite = String(format: "%@,%@,%@,%@,%@, \n", ids[i], names[i], models[i], upcs[i], prices[i])

是您用来创建 CSV 文件的每一行的内容。这仅适用于简单的情况。

这是 CSV 规则:

  1. 如果字段值包含字段分隔符(在您的情况下为逗号)、引号、值两端的空格或任何换行符,则字段值必须用引号引起来(通常是双引号)。<
  2. 如果字段值包含任何引号字符,您必须使用另一个引号字符对每个引号字符进行转义。

创建和解析 CSV 文件比大多数人意识到的要复杂得多。

要么修改您的逻辑以添加任何需要的引用,要么找到能够正确处理所有这些情况的第 3 方 CSV 库。

关于ios - CSV 格式不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34978839/

相关文章:

ios - 显示空单元格的 TableView

ios - XCTest POST API性能测试

powershell - 使用 PowerShell 导入和导出 CSV,所有列都用双引号引起来

javascript - 创建动态文本框然后写入文本文件

ios - 键盘没有提供多个 UIWindows

ios - 是否可以在 iOS 的同一项目中为两个不同的构建(例如开发和生产)设置两个不同的 URL 模式?

ios - iCloud 和核心数据 - "Path is outside of any CloudDocs container, will never sync"

ios - 更改状态栏背景

ios - 闭包执行

读取 R 中包含向量 (c(x,y)) 的 .csv