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

swift 3.1如何从CSV获取数组或字典,csv,parsing,swift3,Csv,Parsing,Swift3,我如何使用这种CSV文件中的数据?或者,如何打印“inside”列的第2行值并将其分配给属性/实体 我有这样的文件,我从excel文件转换成数字,我想抓住每列的数据,并使用它们 以数字形式打开的原始CSV文件: 我得到的控制台输出: 使用这种方法: func readDataFromCSV(fileName:String, fileType: String)-> String!{ guard let filepath = Bundle.main.path(forReso

我如何使用这种CSV文件中的数据?或者,如何打印“inside”列的第2行值并将其分配给属性/实体

我有这样的文件,我从excel文件转换成数字,我想抓住每列的数据,并使用它们

以数字形式打开的原始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
}
感谢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
    }
在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

您要做的是将字符串分为行,然后分为列(基本上是一个二维字符串数组)。Swift已经提供了
String
structs上的方法

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
}
然后,您可以通过以下方式访问任何值:

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

Swift 4

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

Hello, "Complicated String, with a comma inside", 123
在这种情况下,我使用:

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)
     }
 }
let dataString:String!=String.init(数据:data!,编码:.utf8)
变量项:[(字符串,字符串,字符串)]=[]
将行:[String]=dataString.components(分隔符:NSCharacterSet.newlines)设为[String]
排队{
变量值:[字符串]=[]
如果行!“”{
如果line.range(of:“\”)!=nil{
var textToScan:String=line
var值:NSString?
变量textScanner:Scanner=Scanner(字符串:textToScan)
而textScanner.string!“”{
如果(textScanner.string作为NSString)。子字符串(到:1)=“\”“{
textScanner.scanLocation+=1
textScanner.Scanup(“\”,输入:&值)
textScanner.scanLocation+=1
}否则{
textScanner.Scanup(“,”到:&值)
}
values.append(value!作为字符串)
如果textScanner.scanLocation

它是用Swift 4写的,原文来自
这是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)
        }
        }
Swift 5.0 .scanLocaion和.scanUpTo()在iOS13中被弃用

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

}

有什么问题吗?您似乎已经读取了数据。是的,我读取了数据,但我只有一个长字符串,如何打印“inside”的第2行值“列并将其分配给属性/实体?是否尝试搜索堆栈溢出?”?你真的认为你是第一个想要将CSV文件拆分成组件的人吗?很明显,可能是重复的!,事实上,这段代码是我搜索的结果,也是我的另一个问题,但很多人向我解释说CSV很难操作,我最好更改文件扩展名,问题是这是不可能的。而且,所有的解决方案都是针对不同的CSV文件定制的,我不知道如何解决这种问题。最后,swift版本和答案之间的设计模式发生了很大变化,因此我发现将CSV转换为字典或数组的主要步骤甚至很难理解。为了您的帮助,我用您的代码在我的问题中添加了一个测试,但是我想我不明白在数据中放什么:你能检查一下我是否误解了什么吗?我使用的
是指你的
readdatafromsv
方法的结果。它基本上是您读入字符串的csv文件的内容。完成!我应该使用cswRows,用你的解决方案更新整个答案,谢谢你的帮助!如果在值中有特殊字符,例如
,那么这将不起作用。还有更多的逃跑规则。最好找到一个成熟的库来为您解析它。这个解析器(和本页上的任何解析器一样)是有缺陷的。它以新行分隔行开始,这是一个错误的假设。csv文件在双引号中时可能包含一个换行符作为其值。因此,唯一的方法是从一开始就正确地解析,使用一个迷你状态机,不要假设任何东西这个解决方案也不起作用。如果一个值内部有一个换行符(如果该值周围有双引号,这是可能的),那么这也将无法正确解析。它也是不可伸缩的。这个解决方案假设我们只有3列,但是如果您使用的数据集是30列,那么您不应该定义30个元素元组