我正在保存 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)
}
最佳答案
这一行:
let stringToWrite = String(format: "%@,%@,%@,%@,%@, \n", ids[i], names[i], models[i], upcs[i], prices[i])
是您用来创建 CSV 文件的每一行的内容。这仅适用于简单的情况。
这是 CSV 规则:
- 如果字段值包含字段分隔符(在您的情况下为逗号)、引号、值两端的空格或任何换行符,则字段值必须用引号引起来(通常是双引号)。<
- 如果字段值包含任何引号字符,您必须使用另一个引号字符对每个引号字符进行转义。
创建和解析 CSV 文件比大多数人意识到的要复杂得多。
要么修改您的逻辑以添加任何需要的引用,要么找到能够正确处理所有这些情况的第 3 方 CSV 库。
关于ios - CSV 格式不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34978839/