Swift CSVImporter无法读取CSV文件

时间:2018-06-07 14:44:30

标签: swift csv-import

我正在使用CSVImporter窗格来解析从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 { $0 }.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)
    }
}

注意:这是重新发布的问题,因为&#34;重复&#34;以上代码是建议的实现。

我的初始和首选实现是通过documentPicker获取iCloud驱动器文件的链接,并在运行时将其解析/上传到数据库,但我得到的错误与我现在一样:&#34;无法读取CSV文件。&#34;

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."

第二季度:考虑到我不需要保留永久文件 - 只需要保留它直到解析它然后它将在我的数据库中,为什么我需要将其导入documentDirectory ,有什么办法可以通过我从documentPicker获得的链接解析它吗?

我最初实施的代码:

 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 { $0 }.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)
 }
}

1 个答案:

答案 0 :(得分:1)

Q1:

我在docURL尝试解析文件时看到的问题如下:

self.path = String(describing:docURL)

这不是将文件URL转换为路径的正确方法。正确的代码是:

self.path = docURL.path

Q2:

UIDocumentPickerViewController模式下使用import时,委托方法中给出的URL仅在委托方法结束前有效。这就是您必须复制/移动所选文件的原因。

来自文档:

  

URL指的是所选文档的副本。这些文件是临时文件。它们仅在您的应用程序终止之前保持可用。要保留永久副本,请将这些文件移动到沙箱中的永久位置。

所以是的,你必须复制一份。但是,您可以在解析文件后删除该文件。