如何将字典写入文件?
How to write Dictionary to a file?
我有一个 FileHelper class,我在其中实现了 3 个方法,它们的工作是将字典内容写入文件。这些方法是:
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
}
当我调用 FileHelper().storeDictionary(aValidDictionary, inFile: "abc", atDirectory: "XYZ")
编写字典时,此过程失败。但是如果我使用
guard (dictionary as NSDictionary).write(to: filePath!, atomically: true) else {
return false
}
有效。
NSKeyedArchiver.archiveRootObject(_:toFile:)
方法有什么问题??
为什么 FileManager.default.createFile(atPath: (filePath?.absoluteString)!, contents: nil, attributes: nil)
总是 returns 错误?
首先 filePath?.absoluteString
returns 包括 file://
方案在内的整个(甚至百分比转义)字符串,该方法需要一条没有方案的路径(filePath?.path
-命名有点混乱 ;-)).
我建议将 [String:String]
词典保存为 属性 列表文件。无需显式创建文件。
我在 Swift-3-way 中稍微更改了方法的签名。此外,无需使用任何可选类型。
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:您可以使存储方法 可以抛出 并处理调用方法中的错误,而不是返回 Bool
:
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))
}
这是一个 swift 5 扩展,可以保存 Key
和 Value
为 Codable
的任何词典
extension Dictionary where Key: Codable, Value: Codable {
static func load(fromFileName fileName: String, using fileManager: FileManager = .default) -> [Key: Value]? {
let fileURL = Self.getDocumentsURL(on: .cachesDirectory, withName: fileName, using: fileManager)
guard let data = fileManager.contents(atPath: fileURL.path) else { return nil }
do {
return try JSONDecoder().decode([Key: Value].self, from: data)
} catch(let error) {
print(error)
return nil
}
}
func saveToDisk(on directory: FileManager.SearchPathDirectory,
withName name: String,
using fileManager: FileManager = .default) throws {
let fileURL = Self.getDocumentsURL(on: .cachesDirectory, withName: name, using: fileManager)
let data = try JSONEncoder().encode(self)
try data.write(to: fileURL)
}
private static func getDocumentsURL(on directory: FileManager.SearchPathDirectory,
withName name: String,
using fileManager: FileManager) -> URL {
let folderURLs = fileManager.urls(for: .cachesDirectory, in: .userDomainMask)
let fileURL = folderURLs[0].appendingPathComponent(name)
return fileURL
}
}
用法:
let myDict = [MyKey: MyValue].load(from: diskDirectory, andFileName: diskFileName) // load
try myDict.saveToDisk(on: diskDirectory, withName: diskFileName) // save
我有一个 FileHelper class,我在其中实现了 3 个方法,它们的工作是将字典内容写入文件。这些方法是:
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
}
当我调用 FileHelper().storeDictionary(aValidDictionary, inFile: "abc", atDirectory: "XYZ")
编写字典时,此过程失败。但是如果我使用
guard (dictionary as NSDictionary).write(to: filePath!, atomically: true) else {
return false
}
有效。
NSKeyedArchiver.archiveRootObject(_:toFile:)
方法有什么问题??
为什么 FileManager.default.createFile(atPath: (filePath?.absoluteString)!, contents: nil, attributes: nil)
总是 returns 错误?
首先 filePath?.absoluteString
returns 包括 file://
方案在内的整个(甚至百分比转义)字符串,该方法需要一条没有方案的路径(filePath?.path
-命名有点混乱 ;-)).
我建议将 [String:String]
词典保存为 属性 列表文件。无需显式创建文件。
我在 Swift-3-way 中稍微更改了方法的签名。此外,无需使用任何可选类型。
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:您可以使存储方法 可以抛出 并处理调用方法中的错误,而不是返回 Bool
:
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))
}
这是一个 swift 5 扩展,可以保存 Key
和 Value
为 Codable
extension Dictionary where Key: Codable, Value: Codable {
static func load(fromFileName fileName: String, using fileManager: FileManager = .default) -> [Key: Value]? {
let fileURL = Self.getDocumentsURL(on: .cachesDirectory, withName: fileName, using: fileManager)
guard let data = fileManager.contents(atPath: fileURL.path) else { return nil }
do {
return try JSONDecoder().decode([Key: Value].self, from: data)
} catch(let error) {
print(error)
return nil
}
}
func saveToDisk(on directory: FileManager.SearchPathDirectory,
withName name: String,
using fileManager: FileManager = .default) throws {
let fileURL = Self.getDocumentsURL(on: .cachesDirectory, withName: name, using: fileManager)
let data = try JSONEncoder().encode(self)
try data.write(to: fileURL)
}
private static func getDocumentsURL(on directory: FileManager.SearchPathDirectory,
withName name: String,
using fileManager: FileManager) -> URL {
let folderURLs = fileManager.urls(for: .cachesDirectory, in: .userDomainMask)
let fileURL = folderURLs[0].appendingPathComponent(name)
return fileURL
}
}
用法:
let myDict = [MyKey: MyValue].load(from: diskDirectory, andFileName: diskFileName) // load
try myDict.saveToDisk(on: diskDirectory, withName: diskFileName) // save