我需要从一个文本文件读取和写入数据,但我还没有弄清楚怎么做。

我在Swift的iBook中找到了这个示例代码,但我仍然不知道如何写入或读取数据。

import Cocoa

class DataImporter {
    /*
    DataImporter is a class to import data from an external file.
    The class is assumed to take a non-trivial amount of time to initialize.
    */
    var fileName = "data.txt"
    // the DataImporter class would provide data importing functionality here
}

class DataManager {
    @lazy var importer = DataImporter()
    var data = String[]()
    // the DataManager class would provide data management functionality here
}

let manager = DataManager()
manager.data += "Some data"
manager.data += "Some more data"
// the DataImporter instance for the importer property has not yet been created”

println(manager.importer.fileName)
// the DataImporter instance for the importer property has now been created
// prints "data.txt”    

var str = "Hello World in Swift Language."

当前回答

 func writeToDocumentsFile(fileName:String,value:String) {
    let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
    let path = documentsPath.appendingPathComponent(fileName)
    do{
    try value.write(toFile: path, atomically: true, encoding: String.Encoding.utf8)
}catch{
    }
    }

func readFromDocumentsFile(fileName:String) -> String {
    let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
    let path = documentsPath.appendingPathComponent(fileName)
    let checkValidation = FileManager.default
    var file:String

    if checkValidation.fileExists(atPath: path) {
        do{
       try file = NSString(contentsOfFile: path, encoding: String.Encoding.utf8.rawValue) as String
        }catch{
            file = ""
        }
        } else {
        file = ""
    }

    return file
}

其他回答

建议异步读写文件!用纯Swift很容易做到, 以下是协议:

protocol FileRepository {
    func read(from path: String) throws -> String
    func readAsync(from path: String, completion: @escaping (Result<String, Error>) -> Void)
    func write(_ string: String, to path: String) throws
    func writeAsync(_ string: String, to path: String, completion: @escaping (Result<Void, Error>) -> Void)
}

正如您所看到的,它允许您同步或异步地读取和写入文件。

以下是我在Swift 5中的实现:

class DefaultFileRepository {
    
    // MARK: Properties
    
    let queue: DispatchQueue = .global()
    let fileManager: FileManager = .default
    lazy var baseURL: URL = {
        try! fileManager
            .url(for: .libraryDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
            .appendingPathComponent("MyFiles")
    }()
    
    
    // MARK: Private functions
    
    private func doRead(from path: String) throws -> String {
        let url = baseURL.appendingPathComponent(path)
        
        var isDir: ObjCBool = false
        guard fileManager.fileExists(atPath: url.path, isDirectory: &isDir) && !isDir.boolValue else {
            throw ReadWriteError.doesNotExist
        }
        
        let string: String
        do {
            string = try String(contentsOf: url)
        } catch {
            throw ReadWriteError.readFailed(error)
        }
        
        return string
    }
    
    private func doWrite(_ string: String, to path: String) throws {
        let url = baseURL.appendingPathComponent(path)
        let folderURL = url.deletingLastPathComponent()
        
        var isFolderDir: ObjCBool = false
        if fileManager.fileExists(atPath: folderURL.path, isDirectory: &isFolderDir) {
            if !isFolderDir.boolValue {
                throw ReadWriteError.canNotCreateFolder
            }
        } else {
            do {
                try fileManager.createDirectory(at: folderURL, withIntermediateDirectories: true)
            } catch {
                throw ReadWriteError.canNotCreateFolder
            }
        }
        
        var isDir: ObjCBool = false
        guard !fileManager.fileExists(atPath: url.path, isDirectory: &isDir) || !isDir.boolValue else {
            throw ReadWriteError.canNotCreateFile
        }
        
        guard let data = string.data(using: .utf8) else {
            throw ReadWriteError.encodingFailed
        }
        
        do {
            try data.write(to: url)
        } catch {
            throw ReadWriteError.writeFailed(error)
        }
    }
    
}


extension DefaultFileRepository: FileRepository {
    func read(from path: String) throws -> String {
        try queue.sync { try self.doRead(from: path) }
    }
    
    func readAsync(from path: String, completion: @escaping (Result<String, Error>) -> Void) {
        queue.async {
            do {
                let result = try self.doRead(from: path)
                completion(.success(result))
            } catch {
                completion(.failure(error))
            }
        }
    }
    
    func write(_ string: String, to path: String) throws {
        try queue.sync { try self.doWrite(string, to: path) }
    }
    
    func writeAsync(_ string: String, to path: String, completion: @escaping (Result<Void, Error>) -> Void) {
        queue.async {
            do {
                try self.doWrite(string, to: path)
                completion(.success(Void()))
            } catch {
                completion(.failure(error))
            }
        }
    }
    
}


enum ReadWriteError: LocalizedError {
    
    // MARK: Cases
    
    case doesNotExist
    case readFailed(Error)
    case canNotCreateFolder
    case canNotCreateFile
    case encodingFailed
    case writeFailed(Error)
}

这适用于Linux上的Swift 3.1.1:

import Foundation

let s = try! String(contentsOfFile: "yo", encoding: .utf8)

我必须像这样重新编码:

let path = NSBundle.mainBundle().pathForResource("Output_5", ofType: "xml")
let text = try? NSString(contentsOfFile: path! as String, encoding: NSUTF8StringEncoding)
print(text)

假设你已经将你的文本文件data.txt移动到你的Xcode-project中(使用拖放并勾选“必要时复制文件”),你可以像在Objective-C中一样执行以下操作:

let bundle = NSBundle.mainBundle()
let path = bundle.pathForResource("data", ofType: "txt")        
let content = NSString.stringWithContentsOfFile(path) as String

println(content) // prints the content of data.txt

更新: 对于从Bundle (iOS)读取文件,您可以使用:

let path = NSBundle.mainBundle().pathForResource("FileName", ofType: "txt")
var text = String(contentsOfFile: path!, encoding: NSUTF8StringEncoding, error: nil)!
println(text)

Swift 3更新:

let path = Bundle.main.path(forResource: "data", ofType: "txt") // file path for file "data.txt"
var text = String(contentsOfFile: path!, encoding: NSUTF8StringEncoding, error: nil)!

Swift 5

let path = Bundle.main.path(forResource: "ListAlertJson", ofType: "txt") // file path for file "data.txt"
let string = try String(contentsOfFile: path!, encoding: String.Encoding.utf8)

Xcode 8.3.2 Swift 3.x。使用NSKeyedArchiver和NSKeyedUnarchiver

从文档中读取文件

let documentsDirectoryPathString = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let documentsDirectoryPath = NSURL(string: documentsDirectoryPathString)!
let jsonFilePath = documentsDirectoryPath.appendingPathComponent("Filename.json")

let fileManager = FileManager.default
var isDirectory: ObjCBool = false

if fileManager.fileExists(atPath: (jsonFilePath?.absoluteString)!, isDirectory: &isDirectory) {

let finalDataDict = NSKeyedUnarchiver.unarchiveObject(withFile: (jsonFilePath?.absoluteString)!) as! [String: Any]
}
else{
     print("File does not exists")
}

将文件写入文档

NSKeyedArchiver.archiveRootObject(finalDataDict, toFile:(jsonFilePath?.absoluteString)!)