Swift CSVImporter 无法读取 CSV 文件
Swift CSVImporter can't read the CSV file
我正在使用 CSVImporter pod 来解析从 iCloud Drive 上传的 CSV 文件,目的是将解析的每一行上传到我的数据库。
当执行 importFile()
时,它打印路径,然后打印 "The CSV file couldn't be read."
Q1:我做错了什么?
import UIKit
import MobileCoreServices
import CSVImporter
class importBatchVC: UIViewController,UIDocumentPickerDelegate,UINavigationControllerDelegate {
var path=""
var docURL = URL(string: "")
@IBAction func chooseDoc(_ sender: Any) {
let importMenu = UIDocumentPickerViewController(documentTypes: [String(kUTTypeContent),String(kUTTypePlainText)], in: .import)
importMenu.delegate = self
importMenu.modalPresentationStyle = .formSheet
self.present(importMenu, animated: true, completion: nil
}
@IBAction func importFile(_ sender: Any) {
if docURL==nil {
let alert = UIAlertController(title: "Error", message: "Please select a spreadsheet.", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
} else {
do {
self.path = String(describing:docURL)
print(path)
let importer = CSVImporter<[String]>(path: path)
importer.startImportingRecords { [=11=] }.onFail {
print("The CSV file couldn't be read.")
}.onProgress { importedDataLinesCount in
print("\(importedDataLinesCount) lines were already imported.")
}.onFinish { importedRecords in
print("Did finish import with \(importedRecords.count) records.")
}
}
}
}
@IBAction func cancel(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
print("The Url is : \(String(describing: url))")
let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
do {
try FileManager.default.moveItem(at: url.standardizedFileURL, to: documentDirectory.appendingPathComponent(url.lastPathComponent))
self.docURL = documentDirectory.appendingPathComponent(url.lastPathComponent)
print("now check this: \(docURL!)")
} catch {
print(error)
}
}
func documentMenu(_ documentMenu: UIDocumentPickerViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) {
documentPicker.delegate = self
present(documentPicker, animated: true, completion: nil)
}
}
注意:这是已作为 "duplicate" 关闭的转贴问题,上面的代码是建议的实现。
我最初和首选的实现是通过 documentPicker
和 parse/upload 获取 iCloud 驱动器文件的 link 并将其动态传输到数据库,但我遇到了与我现在得到:"The CSV file couldn't be read."
Leo Dabus 提供的解释是:
"UIDocumentPickerModeImport The URL refers to a copy of the selected document. This document is a temporary file. It remains available only until your application terminates. To keep a permanent copy, you must move this file to a permanent location inside your sandbox."
Q2: 考虑到我不需要保留一个永久文件——只需要保留它直到它被解析然后它就会在我的数据库中,为什么我需要将它导入到 documentDirectory
,有什么方法可以通过我从 documentPicker 得到的 link 来解析它?
我的初始实现代码:
import UIKit
import MobileCoreServices
import CSVImporter
class importBatchVC: UIViewController,UIDocumentPickerDelegate,UINavigationControllerDelegate {
var path=""
var docURL = URL(string: "")
@IBAction func chooseDoc(_ sender: Any) {
let importMenu = UIDocumentPickerViewController(documentTypes: [String(kUTTypeContent),String(kUTTypePlainText)], in: .import)
importMenu.delegate = self
importMenu.modalPresentationStyle = .formSheet
self.present(importMenu, animated: true, completion: nil)
}
@IBAction func importFile(_ sender: Any) {
if docURL==nil {
let alert = UIAlertController(title: "Error", message: "Please select a spreadsheet.", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
else{
do {
self.path = docURL!.path
print(path)
let importer = CSVImporter<[String]>(path: path)
importer.startImportingRecords { [=12=] }.onFinish { importedRecords in
for record in importedRecords {
// record is of type [String] and contains all data in a line
print(record)
}
}
}
}
}
@IBAction func cancel(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
docURL = url as URL
print("The Url is : \(String(describing: url))")
}
func documentMenu(_ documentMenu: UIDocumentPickerViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) {
documentPicker.delegate = self
present(documentPicker, animated: true, completion: nil)
}
}
Q1:
我在尝试解析位于 docURL
的文件时看到的问题是以下行:
self.path = String(describing:docURL)
这不是将文件 URL 转换为路径的正确方法。正确的代码是:
self.path = docURL.path
Q2:
当你在import
模式下使用UIDocumentPickerViewController
时,在委托方法中给你的URL只在委托方法结束前有效。这就是为什么您必须 copy/move 选择的文件。
来自文档:
The URLs refer to a copy of the selected documents. These documents are temporary files. They remain available only until your application terminates. To keep a permanent copy, move these files to a permanent location inside your sandbox.
所以是的,您必须复印一份。但是您可以在解析完成后删除该文件。
我正在使用 CSVImporter pod 来解析从 iCloud Drive 上传的 CSV 文件,目的是将解析的每一行上传到我的数据库。
当执行 importFile()
时,它打印路径,然后打印 "The CSV file couldn't be read."
Q1:我做错了什么?
import UIKit
import MobileCoreServices
import CSVImporter
class importBatchVC: UIViewController,UIDocumentPickerDelegate,UINavigationControllerDelegate {
var path=""
var docURL = URL(string: "")
@IBAction func chooseDoc(_ sender: Any) {
let importMenu = UIDocumentPickerViewController(documentTypes: [String(kUTTypeContent),String(kUTTypePlainText)], in: .import)
importMenu.delegate = self
importMenu.modalPresentationStyle = .formSheet
self.present(importMenu, animated: true, completion: nil
}
@IBAction func importFile(_ sender: Any) {
if docURL==nil {
let alert = UIAlertController(title: "Error", message: "Please select a spreadsheet.", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
} else {
do {
self.path = String(describing:docURL)
print(path)
let importer = CSVImporter<[String]>(path: path)
importer.startImportingRecords { [=11=] }.onFail {
print("The CSV file couldn't be read.")
}.onProgress { importedDataLinesCount in
print("\(importedDataLinesCount) lines were already imported.")
}.onFinish { importedRecords in
print("Did finish import with \(importedRecords.count) records.")
}
}
}
}
@IBAction func cancel(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
print("The Url is : \(String(describing: url))")
let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
do {
try FileManager.default.moveItem(at: url.standardizedFileURL, to: documentDirectory.appendingPathComponent(url.lastPathComponent))
self.docURL = documentDirectory.appendingPathComponent(url.lastPathComponent)
print("now check this: \(docURL!)")
} catch {
print(error)
}
}
func documentMenu(_ documentMenu: UIDocumentPickerViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) {
documentPicker.delegate = self
present(documentPicker, animated: true, completion: nil)
}
}
注意:这是已作为 "duplicate" 关闭的转贴问题,上面的代码是建议的实现。
我最初和首选的实现是通过 documentPicker
和 parse/upload 获取 iCloud 驱动器文件的 link 并将其动态传输到数据库,但我遇到了与我现在得到:"The CSV file couldn't be read."
Leo Dabus 提供的解释是:
"UIDocumentPickerModeImport The URL refers to a copy of the selected document. This document is a temporary file. It remains available only until your application terminates. To keep a permanent copy, you must move this file to a permanent location inside your sandbox."
Q2: 考虑到我不需要保留一个永久文件——只需要保留它直到它被解析然后它就会在我的数据库中,为什么我需要将它导入到 documentDirectory
,有什么方法可以通过我从 documentPicker 得到的 link 来解析它?
我的初始实现代码:
import UIKit
import MobileCoreServices
import CSVImporter
class importBatchVC: UIViewController,UIDocumentPickerDelegate,UINavigationControllerDelegate {
var path=""
var docURL = URL(string: "")
@IBAction func chooseDoc(_ sender: Any) {
let importMenu = UIDocumentPickerViewController(documentTypes: [String(kUTTypeContent),String(kUTTypePlainText)], in: .import)
importMenu.delegate = self
importMenu.modalPresentationStyle = .formSheet
self.present(importMenu, animated: true, completion: nil)
}
@IBAction func importFile(_ sender: Any) {
if docURL==nil {
let alert = UIAlertController(title: "Error", message: "Please select a spreadsheet.", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
else{
do {
self.path = docURL!.path
print(path)
let importer = CSVImporter<[String]>(path: path)
importer.startImportingRecords { [=12=] }.onFinish { importedRecords in
for record in importedRecords {
// record is of type [String] and contains all data in a line
print(record)
}
}
}
}
}
@IBAction func cancel(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
docURL = url as URL
print("The Url is : \(String(describing: url))")
}
func documentMenu(_ documentMenu: UIDocumentPickerViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) {
documentPicker.delegate = self
present(documentPicker, animated: true, completion: nil)
}
}
Q1:
我在尝试解析位于 docURL
的文件时看到的问题是以下行:
self.path = String(describing:docURL)
这不是将文件 URL 转换为路径的正确方法。正确的代码是:
self.path = docURL.path
Q2:
当你在import
模式下使用UIDocumentPickerViewController
时,在委托方法中给你的URL只在委托方法结束前有效。这就是为什么您必须 copy/move 选择的文件。
来自文档:
The URLs refer to a copy of the selected documents. These documents are temporary files. They remain available only until your application terminates. To keep a permanent copy, move these files to a permanent location inside your sandbox.
所以是的,您必须复印一份。但是您可以在解析完成后删除该文件。