swiftxcodeswift5nsdocumentdirectory

How do I write a new row a CSV file in documents directory in swift 5?


I have a function where I want to create a CSV file if it doesnt exist and add data to it. If it does exist I want to add this data as a new line each time its called.

Here is my current code, at the moment it just overwrites the entire file each time:

func writeTrackedSymptomValues(symptom: String, comment: String, time: String, timestamp: String) {
    symptomData = SymptomData()
    for _ in 0..<5 {
        symptomData.symptom = symptom
        symptomData.severity = self.severity
        symptomData.comment = comment
        symptomData.timestamp = timestamp
        symptom_data.append(symptomData!)
    }

    creatCSV()
}

func creatCSV() -> Void {
        let fileName = "symptom_data.csv"

        let path = self.getDocumentsDirectory().appendingPathComponent(fileName)
        var csvText = "Symptom,Severity,Comment,Time\n"


            let newLine = "\(symptomData.symptom),\(symptomData.severity),\(symptomData.comment),\(symptomData.timestamp)\n"
            csvText.append(newLine)


        do {
            try csvText.write(to: path, atomically: true, encoding: String.Encoding.utf8)
        } catch {
            print("Failed to create file")
            print("\(error)")
        }
        print(path ?? "not found")
}

func getDocumentsDirectory() -> URL {
    // find all possible documents directories for this user
    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)

    // just send back the first one, which ought to be the only one
    return paths[0]
}

How can I add a new line each time instead?swift


Solution

  • Solved using Warren's advice:

        var logFile: URL? {
            guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return nil }
            let fileName = "symptom_data.csv"
            return documentsDirectory.appendingPathComponent(fileName)
        }
    

    This function checks if the file exists, if not it makes it like in my original question, and if so uses FileManager to add a new line.

        func createCSV() {
            guard let logFile = logFile else {
                return
            }
    
            guard let data = ("\(symptomData.symptom),\(symptomData.severity),\(symptomData.comment),\(symptomData.timestamp)\n").data(using: String.Encoding.utf8) else { return }
    
            if FileManager.default.fileExists(atPath: logFile.path) {
                if let fileHandle = try? FileHandle(forWritingTo: logFile) {
                    fileHandle.seekToEndOfFile()
                    fileHandle.write(data)
                    fileHandle.closeFile()
                }
            } else {
                var csvText = "Symptom,Severity,Comment,Time\n"
    
    
                     let newLine = "\(symptomData.symptom),\(symptomData.severity),\(symptomData.comment),\(symptomData.timestamp)\n"
                     csvText.append(newLine)
    
    
                 do {
                    try csvText.write(to: logFile, atomically: true, encoding: String.Encoding.utf8)
    
                 } catch {
                     print("Failed to create file")
                     print("\(error)")
                 }
                 print(logFile ?? "not found")
            }
        }