3 votes

Comment écrire Dictionnaire dans un fichier ?

J'ai une classe FileHelper dans laquelle j'ai implémenté 3 méthodes dont le rôle est d'écrire le contenu d'un dictionnaire dans un fichier. Ces méthodes sont :

func storeDictionary(_ dictionary: Dictionary<String, String>, inFile fileName: String, atDirectory directory: String) -> Bool {
    let ext = "txt"
    let filePath = createFile(fileName, withExtension: ext, atDirectory: directory)
    /**** //If I use this method, file is created and dictionary is saved
    guard (dictionary as NSDictionary).write(to: filePath!, atomically: true) else {
        return false
    }
    */
    guard NSKeyedArchiver.archiveRootObject(dictionary, toFile: (filePath?.absoluteString)!) else {
        return false
    }
    return true
}
func createFile(_ file: String, withExtension ext: String, atDirectory directory: String) -> URL? {
    let directoryPath = createDirectory(directory)
    let filePath = directoryPath?.appendingPathComponent(file).appendingPathExtension(ext)

    if !FileManager.default.fileExists(atPath: (filePath?.absoluteString)!) {
        let success = FileManager.default.createFile(atPath: (filePath?.absoluteString)!, contents: nil, attributes: nil)
        print("\(success)") //** here is the issue I investigated. Always prints false.
    }

    return filePath
}
func createDirectory(_ directory: String) -> URL? {
    let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let directoryPath = documentsDirectory.appendingPathComponent(directory)

    do {
        try FileManager.default.createDirectory(at: directoryPath, withIntermediateDirectories: true, attributes: nil)
    } catch let error as NSError {
        fatalError("Error creating directory: \(error.localizedDescription)")
    }
    return directoryPath
}

Quand j'appelle FileHelper().storeDictionary(aValidDictionary, inFile: "abc", atDirectory: "XYZ") pour écrire le dictionnaire, il échoue avec cette procédure. Mais si j'utilise

guard (dictionary as NSDictionary).write(to: filePath!, atomically: true) else {
    return false
}

ça marche.

Quel est le problème avec NSKeyedArchiver.archiveRootObject(_:toFile:) méthode ?

Et pourquoi FileManager.default.createFile(atPath: (filePath?.absoluteString)!, contents: nil, attributes: nil) retourne toujours faux ?

7voto

vadian Points 29149

Tout d'abord filePath?.absoluteString renvoie l'intégralité de la chaîne de caractères - même les pourcentages échappés -, y compris les caractères file:// et la méthode s'attend à un chemin sans le schéma ( filePath?.path - la dénomination est un peu confuse ;-) ).

Je recommande d'enregistrer un [String:String] dictionnaire comme fichier de liste de propriétés. Il n'est pas nécessaire de créer le fichier explicitement.

J'ai légèrement modifié les signatures des méthodes dans le fichier Swift-3-way . En outre, il n'est pas nécessaire d'utiliser un type optionnel.

func store(dictionary: Dictionary<String, String>, in fileName: String, at directory: String) -> Bool {
    let fileExtension = "plist"
    let directoryURL = create(directory:directory)
    do {
        let data = try PropertyListSerialization.data(fromPropertyList: dictionary, format: .xml, options: 0)
        try data.write(to: directoryURL.appendingPathComponent(fileName).appendingPathExtension(fileExtension))
        return true
    }  catch {
        print(error)
        return false
    }
}

func create(directory: String) -> URL {
    let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let directoryURL = documentsDirectory.appendingPathComponent(directory)

    do {
        try FileManager.default.createDirectory(at: directoryURL, withIntermediateDirectories: true, attributes: nil)
    } catch let error as NSError {
        fatalError("Error creating directory: \(error.localizedDescription)")
    }
    return directoryURL
}

PS : Au lieu de renvoyer un Bool vous pourriez faire en sorte que la méthode de stockage peut jeter et traiter l'erreur dans la méthode d'appel :

func store(dictionary: Dictionary<String, String>, in fileName: String, at directory: String) throws {
    let fileExtension = "plist"
    let directoryURL = create(directory:directory)

    let data = try PropertyListSerialization.data(fromPropertyList: dictionary, format: .xml, options: 0)
    try data.write(to: directoryURL.appendingPathComponent(fileName).appendingPathExtension(fileExtension))
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X