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

我在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."

当前回答

最新swift3代码 你可以从文本文件读取数据,只需使用下面的代码 这是我的文本文件

     {
"NumberOfSlices": "8",
"NrScenes": "5",
"Scenes": [{
           "dataType": "label1",
           "image":"http://is3.mzstatic.com/image/thumb/Purple19/v4/6e/81/31/6e8131cf-2092-3cd3-534c-28e129897ca9/mzl.syvaewyp.png/53x53bb-85.png",

           "value": "Hello",
           "color": "(UIColor.red)"
           }, {
           "dataType": "label2",
           "image":"http://is1.mzstatic.com/image/thumb/Purple71/v4/6c/4c/c1/6c4cc1bc-8f94-7b13-f3aa-84c41443caf3/mzl.hcqvmrix.png/53x53bb-85.png",
           "value": "Hi There",
           "color": "(UIColor.blue)"
           }, {
           "dataType": "label3",
           "image":"http://is1.mzstatic.com/image/thumb/Purple71/v4/6c/4c/c1/6c4cc1bc-8f94-7b13-f3aa-84c41443caf3/mzl.hcqvmrix.png/53x53bb-85.png",

           "value": "hi how r u ",
           "color": "(UIColor.green)"
           }, {
           "dataType": "label4",
           "image":"http://is1.mzstatic.com/image/thumb/Purple71/v4/6c/4c/c1/6c4cc1bc-8f94-7b13-f3aa-84c41443caf3/mzl.hcqvmrix.png/53x53bb-85.png",
           "value": "what are u doing  ",
           "color": "(UIColor.purple)"
           }, {
           "dataType": "label5",
          "image":"http://is1.mzstatic.com/image/thumb/Purple71/v4/6c/4c/c1/6c4cc1bc-8f94-7b13-f3aa-84c41443caf3/mzl.hcqvmrix.png/53x53bb-85.png",
           "value": "how many times ",
           "color": "(UIColor.white)"
           }, {
           "dataType": "label6",
           "image":"http://is1.mzstatic.com/image/thumb/Purple71/v4/5a/f3/06/5af306b0-7cac-1808-f440-bab7a0d18ec0/mzl.towjvmpm.png/53x53bb-85.png",
           "value": "hi how r u ",
           "color": "(UIColor.blue)"
           }, {
           "dataType": "label7",
           "image":"http://is5.mzstatic.com/image/thumb/Purple71/v4/a8/dc/eb/a8dceb29-6daf-ca0f-d037-df9f34cdc476/mzl.ukhhsxik.png/53x53bb-85.png",
           "value": "hi how r u ",
           "color": "(UIColor.gry)"
           }, {
           "dataType": "label8",
           "image":"http://is2.mzstatic.com/image/thumb/Purple71/v4/15/23/e0/1523e03c-fff2-291e-80a7-73f35d45c7e5/mzl.zejcvahm.png/53x53bb-85.png",
           "value": "hi how r u ",
           "color": "(UIColor.brown)"
           }]

}

你可以使用这段代码从swift3的文本json文件中获取数据

     let filePath = Bundle.main.path(forResource: "nameoftheyourjsonTextfile", ofType: "json")


    let contentData = FileManager.default.contents(atPath: filePath!)
    let content = NSString(data: contentData!, encoding: String.Encoding.utf8.rawValue) as? String

    print(content)
    let json = try! JSONSerialization.jsonObject(with: contentData!) as! NSDictionary
    print(json)
    let app = json.object(forKey: "Scenes") as! NSArray!
    let _ : NSDictionary
    for dict in app! {
        let colorNam = (dict as AnyObject).object(forKey: "color") as! String
        print("colors are \(colorNam)")

       // let colour = UIColor(hexString: colorNam) {
       // colorsArray.append(colour.cgColor)
       // colorsArray.append(colorNam  as! UIColor)

        let value = (dict as AnyObject).object(forKey: "value") as! String
        print("the values are \(value)")
        valuesArray.append(value)

        let images = (dict as AnyObject).object(forKey: "image") as! String
        let url = URL(string: images as String)
        let data = try? Data(contentsOf: url!)
        print(data)
        let image1 = UIImage(data: data!)! as UIImage
        imagesArray.append(image1)
         print(image1)
            }

其他回答

建议异步读写文件!用纯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)
}

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)!)

Xcode 8。3. Swift;X或以上

do {
    // get the documents folder url
    if let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
        // create the destination url for the text file to be saved
        let fileURL = documentDirectory.appendingPathComponent("file.txt")
        // define the string/text to be saved
        let text = "Hello World !!!"
        // writing to disk 
        // Note: if you set atomically to true it will overwrite the file if it exists without a warning
        try text.write(to: fileURL, atomically: false, encoding: .utf8)
        print("saving was successful")
        // any posterior code goes here
        // reading from disk
        let savedText = try String(contentsOf: fileURL)
        print("savedText:", savedText)   // "Hello World !!!\n"
    }
} catch {
    print("error:", error)
}

早期的解决方案回答了问题,但在我的情况下,删除文件的旧内容而写入是一个问题。

所以,我创建了一段代码写入文件目录中的文件,而不删除以前的内容。您可能需要更好的错误处理,但我相信这是一个很好的起点。斯威夫特4。 Usuage:

    let filename = "test.txt"
    createOrOverwriteEmptyFileInDocuments(filename: filename)
    if let handle = getHandleForFileInDocuments(filename: filename) {
        writeString(string: "aaa", fileHandle: handle)
        writeString(string: "bbb", fileHandle: handle)
        writeString(string: "\n", fileHandle: handle)
        writeString(string: "ccc", fileHandle: handle)
    }

辅助方法:

func createOrOverwriteEmptyFileInDocuments(filename: String){
    guard let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
        debugPrint("ERROR IN createOrOverwriteEmptyFileInDocuments")
        return
    }
    let fileURL = dir.appendingPathComponent(filename)
    do {
        try "".write(to: fileURL, atomically: true, encoding: .utf8)
    }
    catch {
        debugPrint("ERROR WRITING STRING: " + error.localizedDescription)
    }
    debugPrint("FILE CREATED: " + fileURL.absoluteString)
}

private func writeString(string: String, fileHandle: FileHandle){
    let data = string.data(using: String.Encoding.utf8)
    guard let dataU = data else {
        debugPrint("ERROR WRITING STRING: " + string)
        return
    }
    fileHandle.seekToEndOfFile()
    fileHandle.write(dataU)
}

private func getHandleForFileInDocuments(filename: String)->FileHandle?{
    guard let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
        debugPrint("ERROR OPENING FILE")
        return nil
    }
    let fileURL = dir.appendingPathComponent(filename)
    do {
        let fileHandle: FileHandle? = try FileHandle(forWritingTo: fileURL)
        return fileHandle
    }
    catch {
        debugPrint("ERROR OPENING FILE: " + error.localizedDescription)
        return nil
    }
}
 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
}