将数据保存在数组和/或字典中的文本文件中

时间:2015-03-17 08:11:23

标签: ios xcode swift

我坚持编程步骤。我希望你能帮助我。

我在文本文件中输入了以下行:

#Objekt
Objektnr; 1000000;
Filialname; Dresden;
Filialeemail; email@email.com;

#Baustelle
Anschrift1;;
Anschrift2;Juwelier Schubert;
Strasse;Theresienstrafle 7;
Land;DE;
Ort;TheTown;
PLZ;12345;

....

我有以下函数将文件数据带到数组或字典中。在另一个函数中,我将数据保存到本地CoreData-Database。

func startImportTextfile(fileName: String, fileDir: String) -> Bool {

    var filePath : String = folderDocuments.stringByAppendingPathComponent(fileDir)
    var fileNameWithPath = filePath.stringByAppendingPathComponent(fileName)

    var fullImportContent = String(contentsOfFile: fileNameWithPath, encoding: NSUTF8StringEncoding, error: nil)

    if(fullImportContent != "")
    {

        var stringArray = fullImportContent!.componentsSeparatedByString("\n")
        var stringArrayCompleteData = Dictionary<String, Array<Any>>()
        var arrIndexSection : String = "NoHeader"

        for singleRow in stringArray
        {
            if(singleRow != "")
            {
                switch singleRow {
                    case "#Header":
                        arrIndexSection = singleRow.stringByReplacingOccurrencesOfString("#", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
                    case "#Objekt":
                        arrIndexSection = singleRow.stringByReplacingOccurrencesOfString("#", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
                    case "#Baustelle":
                        arrIndexSection = singleRow.stringByReplacingOccurrencesOfString("#", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
                    case "#Auftraggeber":
                        arrIndexSection = singleRow.stringByReplacingOccurrencesOfString("#", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
                    case "#Architekt":
                        arrIndexSection = singleRow.stringByReplacingOccurrencesOfString("#", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
                    case "#Vermittler":
                        arrIndexSection = singleRow.stringByReplacingOccurrencesOfString("#", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
                    case "#Regulierer":
                        arrIndexSection = singleRow.stringByReplacingOccurrencesOfString("#", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
                    case "#Versicherung":
                        arrIndexSection = singleRow.stringByReplacingOccurrencesOfString("#", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
                    case "#Kontaktstellen":
                        arrIndexSection = singleRow.stringByReplacingOccurrencesOfString("#", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
                    case "#Dateien":
                        arrIndexSection = singleRow.stringByReplacingOccurrencesOfString("#", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
                    default:
                        //Here the multiple array would be filled
                        var arrSingleRow = singleRow.componentsSeparatedByString(";")

                        if( arrSingleRow.count > 0  )
                        {
                            if( arrIndexSection == "Kontaktstellen" )
                            {
                                //TODO: Kontaktstellen einlesen

                                //#Kontaktstellen
                                //Baustelle;0;348873;;;;0
                                //Baustelle;0;381263;;Albrecht;0815;0
                                //Regulierer/SV;0;171979;Josef;Eder;08546/911055;0
                                println( "Kontaktstellendaten" )
                                println( singleRow )
                            }
                            else if( arrIndexSection == "Dateien" )
                            {
                                //TODO: Dateien einlesen

                                //#Dateien
                                //11022015090007_BEmail_INNNUE_21102014141534.pdf; 99; Email an asdfasdf@sdf.de

                                println( "Dateiendaten" )
                                println( singleRow )
                            }
                            else
                            {
                                stringArrayCompleteData[arrIndexSection] = [arrSingleRow[0]: arrSingleRow[1]]
                            }
                        }
                }
            }
        }

        for key in stringArrayCompleteData {
            println("Key: \(key)")
        }
        return true
    }
    else
    {
        return false
    }

}

目的是我可以打开这样的数据:

println(stringArrayCompleteData["Objekt"].Objektnr)

但我不知道如何声明stringArrayCompleteData。

也许我必须改变这种贬值

var stringArrayCompleteData = Dictionary<String, Array<Any>>()

var stringArrayCompleteData = Array<String, Dictionary<String, Any>>()

感谢您的每一个小帮助

3 个答案:

答案 0 :(得分:2)

我放置了一个包含数据的文本文件并保存在文档目录中的文本文件中,并将文本文件名和目录路径传递给函数,函数返回字典,其中的数据以字典格式存入

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {

        super.viewDidLoad()

        let fileDirectory : [String] = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as [String]

        var fileDir = fileDirectory[0]

        var returnedDictionary : Dictionary = self.startImportTextfile("textdata", fileDir: fileDir)

        println(returnedDictionary)

        var keyDictionary : Dictionary! = returnedDictionary["Objekt"]

        println(keyDictionary["Objektnr"] as String!)
    }

    func startImportTextfile(fileName: String, fileDir: String) -> Dictionary<String,Dictionary<String,String>> {


        let fileNameWithPath :String! = fileDir.stringByAppendingPathComponent(fileName)

        var err: NSError?

        var currentKey : String!

        let fullImportContent :String! = String.stringWithContentsOfFile(fileNameWithPath!, encoding: NSUTF8StringEncoding, error: &err)

        var dataDictionary = [String : Dictionary <String,String>]()

        if(fullImportContent != "")
        {
            var singleLineArray = fullImportContent!.componentsSeparatedByString("\n")

            for singleRow in singleLineArray
            {
                if(singleRow != "")
                {
                    switch singleRow
                    {

                    case "#Header","#Objekt","#Baustelle","#Auftraggeber","#Architekt","#Vermittler","#Regulierer","#Versicherung","#Kontaktstellen","#Dateien":
                        currentKey = singleRow.stringByReplacingOccurrencesOfString("#", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
                        dataDictionary[currentKey] = Dictionary <String,String>()

                    default:
                        var arrayForSingleRow = singleRow.componentsSeparatedByString(";")

                        if( arrayForSingleRow.count > 0  )
                        {
                            var sampledict : Dictionary! = dataDictionary[currentKey]

                            sampledict[arrayForSingleRow[0]] = arrayForSingleRow[1]

                            dataDictionary[currentKey] = sampledict

                        }
                    }
                }
            }
        }

        return dataDictionary

    }

}

执行后,我得到以下输出:

[Objekt:[Filialname:Dresden,Objektnr:1000000,Filialeemail:email @],Baustelle:[PLZ:12345,Ort:TheTown,Land:DE,Anschrift1:,Strasse:Theresienstra fl e 7,Anschrift2:Juwelier Schubert]]  百万

其中 Objekt 是密钥,它包含字典值,您可以从该字典中访问 Objektnr ,就像我在viewDidLoad中所做的那样。

链接到文本文件:https://www.dropbox.com/s/oyzbo128zr3jd6h/textdata?dl=0

答案 1 :(得分:2)

嗨罗兰 - 我的建议是将文本分成不同的部分,并将每个部分放入一个结构中。例如,您将定义一个包含3个属性的Objekt结构:objektnr,filialname和filialeemail。

例如,您可以使用根Person结构创建结构树。 Person结构将包含与Objekt结构实例,Bastille结构实例等对应的属性


这是一些定义结构的示例代码:

struct Person:Printable {
    init() {
    }
    var objektStruct:Objekt?
    var baustelleStruct:Baustelle?


    var description:String {
        get {
            let objektStructDescription = objektStruct != nil ? objektStruct!.description : ""
            let baustelleStructDescription = baustelleStruct != nil ? baustelleStruct!.description : ""
            return "\(objektStructDescription)\n\n\(baustelleStructDescription)"
        }
    }
}

struct Objekt:Printable {
    var objektnr:Int = 0
    var filialname:String = ""
    var filialeemail:String = ""

    init(text:String) {
        // Divide the text into an array of lines
        let textLinesArray:[String] = text.componentsSeparatedByString("\n")

        // Loop through each line and set the corresponding property
        for textLine:String in textLinesArray {
            // Separate the components of the line at each ";" character
            var components:[String] = textLine.componentsSeparatedByString(";")
            components = components.map({ (componentString:String) -> String in
                return componentString.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
            })

            // Get the key and value for the line.
            let key:String = components.count > 0 ? components[0] : ""
            let value:String = components.count > 1 ? components[1] : ""

            // Based on the key, set the appropriate property value
            switch key {
            case "Objektnr":
                if let valueAsInt = value.toInt() {
                    objektnr = valueAsInt
                }
            case "Filialname":
                filialname = value
            case "Filialeemail":
                filialeemail = value
            default:
                break
            }
        }
    }

    var description:String {
        get {
            return "*Objekt*\n Objektnr = \(objektnr)\n Filialname = \(filialname)\n Filialeemail = \(filialeemail)"
        }
    }
}

struct Baustelle:Printable {
    var anschrift1:String = ""
    var anschrift2:String = ""
    var strasse:String = ""
    var land:String = ""
    var ort:String = ""
    var plz:Int = 0

    init(text:String) {
        // Divide the text into an array of lines
        let textLinesArray:[String] = text.componentsSeparatedByString("\n")

        // Loop through each line and set the corresponding property
        for textLine:String in textLinesArray {
            // Separate the components of the line at each ";" character
            var components:[String] = textLine.componentsSeparatedByString(";")
            components = components.map({ (componentString:String) -> String in
                return componentString.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
            })

            // Get the key and value for the line.
            let key:String = components.count > 0 ? components[0] : ""
            let value:String = components.count > 1 ? components[1] : ""

            // Based on the key, set the appropriate property value
            switch key {
            case "Anschrift1":
                anschrift1 = value
            case "Anschrift2":
                anschrift2 = value
            case "Strasse":
                strasse = value
            case "Land":
                land = value
            case "Ort":
                ort = value
            case "PLZ":
                if let valueAsInt = value.toInt() {
                    plz = valueAsInt
                }
            default:
                break
            }
        }
    }

    var description:String {
        get {
            return "*Baustelle*\n Anschrift1 = \(anschrift1)\n Anschrift2 = \(anschrift2)\n Strasse = \(strasse)\n Land = \(land)\n Ort = \(ort)\n PLZ = \(plz)"
        }
    }
}

我为Objekt和Baustelle编写了init方法,以便可以提供整个文本部分,并且struct负责将其解析为不同的属性。


以下是使用上述结构的一些示例代码:

let text = String(contentsOfFile: "/Users/markstone/Downloads/textdata.txt")!

// Divide the text at each double newline into multiline sections.
// Eg., the arrayOfTextSections[0] will be the multiline string:
//      #Objekt
//      Objektnr; 1000000;
//      Filialname; Dresden;
//      Filialeemail; email@
let arrayOfTextSections = text.componentsSeparatedByString("\n\n")

// Create an empty Person struct instance. We'll fill it in the loop below
var person = Person()

for textSection in arrayOfTextSections {
    // For each text section, find out the heading (eg., #Objekt or #Baustelle).
    let sectionStringArray = textSection.componentsSeparatedByString("\n")
    let sectionHeading = sectionStringArray[0]

    switch sectionHeading {
    case "#Objekt":
        // Create a new instance of the Objekt using the multiline text in this section, and set this instance to the person.objektStruct property.
        person.objektStruct = Objekt(text: textSection)
    case "#Baustelle":
        // Create a new instance of the Baustelle using the multiline text in this section, and set this instance to the person.baustelleStruct property.
        person.baustelleStruct = Baustelle(text: textSection)
    default:
        break
    }
}

print(person)

print(person)行打印以下输出:

*Objekt*
 Objektnr = 0
 Filialname =  Dresden
 Filialeemail =  email@email.com

*Baustelle*
 Anschrift1 = 
 Anschrift2 = Juwelier Schubert
 Strasse = Theresienstrafle 7
 Land = DE
 Ort = TheTown
 PLZ = 12345

通过这种方法,将结构实例转换为核心数据存储的托管对象非常容易。

答案 2 :(得分:1)

看起来你的猜测是正确的,你的意思是宣称stringArrayCompleteData确实是字典字典,Any作为字典的值类型。顺便说一句,您可以将该类型更加整齐地声明为[String: [String:Any]]

但是,您是否只想将详细信息存储为字符串?或者你打算将数字解析为整数?如果您想要一些更强类型的值,作为使用Any作为数据类型的替代方法,您可能需要考虑使用an enum with associated values

这是您的代码版本,它将存储数据记录并将其插入密钥下。这可能会很多,但也使用了一些你可能会觉得有用的Swift功能。

import Foundation
let folderDocuments = "/"

// rather than return true/false, you could return the data as an optional
func startImportTextfile(fileName: String, fileDir: String) -> [String: [String:String]]? {

    let filePath: String = folderDocuments.stringByAppendingPathComponent(fileDir)
    let fileNameWithPath = filePath.stringByAppendingPathComponent(fileName)

    var error: NSError?
    let fullImportContent = String(contentsOfFile: fileNameWithPath, encoding: NSUTF8StringEncoding, error: &error)

    if let data = fullImportContent where !data.isEmpty   {

        let stringArray = split(data) { $0 == "\n" }
        var completeData: [String: [String:String]] = [:]
        var sectionEntries: [String:String] = [:]
        var arrIndexSection: String? = nil

        for singleRow in stringArray {
            // first is an easy and safe way to check if first character
            // has a specific value, whilst handling empty strings
            if first(singleRow) == "#" {
                // insert records from previous section
                if let header = arrIndexSection {
                    completeData[header] = sectionEntries
                }
                // start a new section
                // dropFirst removes the first "#"
                arrIndexSection = dropFirst(singleRow)
                sectionEntries = [:]
            }
            else {
                let arrSingleRow = split(singleRow) { $0 == ";" }

                if( arrSingleRow.count > 0  ) {
                    switch arrIndexSection {
                    case .Some("Kontaktstellen"):
                        //TODO: Kontaktstellen einlesen
                        println( "Kontaktstellendaten" )
                        println( singleRow )
                    case .Some("Dateien"):
                        //TODO: Dateien einlesen
                        println( "Dateiendaten" )
                        println( singleRow )
                    default:
                        if let label = first(arrSingleRow) {
                            sectionEntries[label] = first(dropFirst(arrSingleRow)) ?? ""
                        }
                    }
                }
            }
        }

        if let header = arrIndexSection {
            completeData[header] = sectionEntries
        }

        return completeData
    }

    println("fail: \(error)")
    return nil
}

if let data = startImportTextfile(Process.arguments[1], Process.arguments[2]) {
    for (key,value) in data {
        println("Key: \(key)\nData: \(value)")
    }
}