【问题标题】:Swift CSVImporter can't read the CSV fileSwift CSVImporter 无法读取 CSV 文件
【发布时间】:2018-11-17 12:57:51
【问题描述】:

我正在使用 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 { $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)
    }
}

注意:这是作为“重复”关闭的转发问题,上面的代码是建议的实现。

我最初和首选的实现是通过documentPicker 获取 iCloud 驱动器文件的链接并即时解析/上传到数据库,但我遇到了与现在相同的错误:“CSV 文件无法”不能读。”

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 获得的链接来解析它吗?

我的初始实现代码:

 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)
 }
}

【问题讨论】:

    标签: swift csv-import


    【解决方案1】:

    第一季度:

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

    self.path = String(describing:docURL)
    

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

    self.path = docURL.path
    

    第二季度:

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

    来自文档:

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

    所以是的,您必须制作副本。但是你可以在解析完成后删除文件。

    【讨论】:

    • Q1:有效!! Q2:`它们仅在您的应用程序终止之前保持可用'-我很好,一旦它被解析,我就不再需要它了!如果我把我的初始实现也放在:让内容=尝试! String(contentsOf: icloudDriveURL!, encoding: String.Encoding.utf8) 我可以打印所选文件中的所有行!那么为什么我可以阅读它,但我无法用 CSVImporter 解析它?请帮助我理解。
    • 您刚刚说“Q1:它有效!!” 那为什么在您的评论末尾说您无法解析它?
    • 使用“制作副本”实现它可以工作。 Q2:是指尝试通过 documentPicker 链接解析它而不在本地复制文件,我对 Q2 的回复指的是。
    • 我无法回答这个问题,因为您没有在问题中提供该代码。
    • 我已经编辑了我的问题,为我的初始和首选实现添加了代码,现在根据您的建议更改 docURL 路径后,它可以通过保存或仅使用 documentPicker 链接来工作。我想我的问题应该是:我可以通过它的 documentPicker 链接从 icloud 驱动器中解析一个文件(一次,然后我不再需要它)吗? ,显然我似乎可以......羞耻我原来的问题被标记为重复
    猜你喜欢
    • 2020-03-23
    • 2021-10-11
    • 1970-01-01
    • 2017-11-24
    • 2021-10-09
    • 2020-03-11
    • 1970-01-01
    • 1970-01-01
    • 2018-12-14
    相关资源
    最近更新 更多