swift 3.1如何从CSV获取数组或字典

big*_*ree 23 csv parsing swift3

我怎样才能在这种CSV文件中使用数据?或者我如何打印"内部"列的第2行值并将其分配给属性/实体?

我有这样的文件,我从excel文件转换为Numbers,我想获取每列的数据并使用它们.

以数字打开的原始CSV文件:

在此输入图像描述

我得到的控制台输出:

在此输入图像描述

使用这种方法:

func readDataFromCSV(fileName:String, fileType: String)-> String!{
        guard let filepath = Bundle.main.path(forResource: fileName, ofType: fileType)
            else {
                return nil
        }
        do {
            var contents = try String(contentsOfFile: filepath, encoding: .utf8)
            contents = cleanRows(file: contents)
            return contents
        } catch {
            print("File Read Error for file \(filepath)")
            return nil
        }
    }


func cleanRows(file:String)->String{
    var cleanFile = file
    cleanFile = cleanFile.replacingOccurrences(of: "\r", with: "\n")
    cleanFile = cleanFile.replacingOccurrences(of: "\n\n", with: "\n")
    //        cleanFile = cleanFile.replacingOccurrences(of: ";;", with: "")
    //        cleanFile = cleanFile.replacingOccurrences(of: ";\n", with: "")
    return cleanFile
}
Run Code Online (Sandbox Code Playgroud)

解决方案感谢Jens Meder

运用

 func csv(data: String) -> [[String]] {
        var result: [[String]] = []
        let rows = data.components(separatedBy: "\n")
        for row in rows {
            let columns = row.components(separatedBy: ";")
            result.append(columns)
        }
        return result
    }
Run Code Online (Sandbox Code Playgroud)

在viewDidLoad中

var data = readDataFromCSV(fileName: kCSVFileName, fileType: kCSVFileExtension)
    data = cleanRows(file: data!)
    let csvRows = csv(data: data!)
    print(csvRows[1][1]) // UXM n. 166/167
Run Code Online (Sandbox Code Playgroud)

Jen*_*der 21

你想要做的是将字符串分成行然后分成列(基本上是字符串的二维数组).Swift已经为结构提供了components方法String.

func csv(data: String) -> [[String]] {
    var result: [[String]] = []
    let rows = data.components(separatedBy: "\n")
    for row in rows {
        let columns = row.components(separatedBy: ";")
        result.append(columns)
    }
    return result
}
Run Code Online (Sandbox Code Playgroud)

然后您可以通过以下方式访问任何值

var data = readDataFromCSV(fileName: kCSVFileName, fileType: kCSVFileExtension)
data = cleanRows(file: data)
let csvRows = csv(data: data)
print(csvRows[1][1]) //UXM n. 166/167.
Run Code Online (Sandbox Code Playgroud)

  • 如果值中有特殊字符,例如字符串之一中的“;”,这将不起作用。还有更多的转义规则。最好找一个成熟的库来为你解析。 (5认同)

wli*_*xcc 19

从iOS15开始官方有一个新的框架叫TabularData,尝试使用它。

import TabularData

let url = Bundle.main.url(forResource: "csvFileName", withExtension: "csv")!
let result = try? DataFrame(contentsOfCSVFile: url)
print(result)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

然后你可以将它们转换成你需要的数据模型

关于 TabularData(WWDC) 的更多详细信息

  • 这应该是 2022 年公认的答案 (4认同)

小智 12

?这是用于 Swift 4.2 的 CSV 文件,地址为 20181208

  var dataArray : [String] = []
      if  let path = Bundle.main.path(yourfile: "svenskaidiom", ofType: "csv")  
      {
        dataArray = []
        let url = URL(fileURLWithPath: path)
        do {
            let data = try Data(contentsOf: url) 
            let dataEncoded = String(data: data, encoding: .utf8)
            if  let dataArr = dataEncoded?.components(separatedBy: "\r\n").map({ $0.components(separatedBy: ";") })
          {
            for line in dataArr
            {
                    dataArray?.append(line)
            }
        }
        }
        catch let jsonErr {
            print("\n Error read CSV file: \n ", jsonErr)
        }
        }
Run Code Online (Sandbox Code Playgroud)


Rob*_*b.R 10

Swift 5.0 .scanLocaion 和 .scanUpTo() 在 iOS13 中已弃用。这是 Chhaileng 答案的工作版本。

 func openCSV(fileName:String, fileType: String)-> String!{
    guard let filepath = Bundle.main.path(forResource: fileName, ofType: fileType)
        else {
            return nil
    }
    do {
        let contents = try String(contentsOfFile: filepath, encoding: .utf8)

        return contents
    } catch {
        print("File Read Error for file \(filepath)")
        return nil
    }
}

 func parseCSV(){

    let dataString: String! = openCSV(fileName: "MeislinDemo", fileType: "csv")
    var items: [(String, String, String)] = []
    let lines: [String] = dataString.components(separatedBy: NSCharacterSet.newlines) as [String]

    for line in lines {
       var values: [String] = []
       if line != "" {
           if line.range(of: "\"") != nil {
               var textToScan:String = line
               var value:String?
               var textScanner:Scanner = Scanner(string: textToScan)
            while !textScanner.isAtEnd {
                   if (textScanner.string as NSString).substring(to: 1) == "\"" {


                       textScanner.currentIndex = textScanner.string.index(after: textScanner.currentIndex)

                       value = textScanner.scanUpToString("\"")
                       textScanner.currentIndex = textScanner.string.index(after: textScanner.currentIndex)
                   } else {
                       value = textScanner.scanUpToString(",")
                   }

                    values.append(value! as String)

                if !textScanner.isAtEnd{
                        let indexPlusOne = textScanner.string.index(after: textScanner.currentIndex)

                    textToScan = String(textScanner.string[indexPlusOne...])
                    } else {
                        textToScan = ""
                    }
                    textScanner = Scanner(string: textToScan)
               }

               // For a line without double quotes, we can simply separate the string
               // by using the delimiter (e.g. comma)
           } else  {
               values = line.components(separatedBy: ",")
           }

           // Put the values into the tuple and add it to the items array
           let item = (values[0], values[1], values[2])
           items.append(item)
           print(item.0)
           print(item.1)
           print(item.2)
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 该解析器(与本页上的任何解析器一样)存在缺陷。它从按换行符分割行开始,这是一个错误的假设。csv 文件可能包含换行符,因为它的值用双引号引起来。因此,唯一的方法是从一开始就正确解析,使用迷你状态机,并且不要假设任何事情 (6认同)

Chh*_*eng 9

斯威夫特4

有时CSV文件更加复杂,例如特殊字符(例如逗号),其值用双引号引起来,如下所示:

Hello, "Complicated String, with a comma inside", 123
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我使用:

let dataString: String! = String.init(data: data!, encoding: .utf8)
var items: [(String, String, String)] = []
let lines: [String] = dataString.components(separatedBy: NSCharacterSet.newlines) as [String]

for line in lines {
    var values: [String] = []
    if line != "" {
        if line.range(of: "\"") != nil {
            var textToScan:String = line
            var value:NSString?
            var textScanner:Scanner = Scanner(string: textToScan)
            while textScanner.string != "" {
                if (textScanner.string as NSString).substring(to: 1) == "\"" {
                    textScanner.scanLocation += 1
                    textScanner.scanUpTo("\"", into: &value)
                    textScanner.scanLocation += 1
                } else {
                    textScanner.scanUpTo(",", into: &value)
                }

                 values.append(value! as String)

                 if textScanner.scanLocation < textScanner.string.count {
                     textToScan = (textScanner.string as NSString).substring(from: textScanner.scanLocation + 1)
                 } else {
                     textToScan = ""
                 }
                 textScanner = Scanner(string: textToScan)
            }

            // For a line without double quotes, we can simply separate the string
            // by using the delimiter (e.g. comma)
        } else  {
            values = line.components(separatedBy: ",")
        }

        // Put the values into the tuple and add it to the items array
        let item = (values[0], values[1], values[2])
        items.append(item)
        print(item.1)
        print(item.2)
        print(item.3)
     }
 }
Run Code Online (Sandbox Code Playgroud)

它只是用Swift 4编写的,原文来自https://www.appcoda.com/core-data-preload-sqlite-database/