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

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

当前回答

我必须像这样重新编码:

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

其他回答

Xcode 8, Swift 3从应用程序包中读取文件的方法:

if let path = Bundle.main.path(forResource: filename, ofType: nil) {
    do {
        let text = try String(contentsOfFile: path, encoding: String.Encoding.utf8)
        print(text)
    } catch {
        printError("Failed to read text from \(filename)")
    }
} else {
    printError("Failed to load file from app bundle \(filename)")
} 

这是一个方便的复制和粘贴扩展

public extension String {
    func contentsOrBlank()->String {
        if let path = Bundle.main.path(forResource:self , ofType: nil) {
            do {
                let text = try String(contentsOfFile:path, encoding: String.Encoding.utf8)
                return text
                } catch { print("Failed to read text from bundle file \(self)") }
        } else { print("Failed to load file from bundle \(self)") }
        return ""
    }
    }

例如

let t = "yourFile.txt".contentsOrBlank()

你几乎总是想要一个行数组:

let r:[String] = "yourFile.txt"
     .contentsOrBlank()
     .characters
     .split(separator: "\n", omittingEmptySubsequences:ignore)
     .map(String.init)

写入ViewDidLoad

var error: NSError?
var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
var documentsDirectory = paths.first as String
var dataPath = documentsDirectory.stringByAppendingPathComponent("MyFolder")

if !NSFileManager.defaultManager().fileExistsAtPath(dataPath) {
    NSFileManager.defaultManager().createDirectoryAtPath(dataPath, withIntermediateDirectories: false, attributes: nil, error: &error)
} else {
    println("not creted or exist")
}

func listDocumentDirectoryfiles() -> [String] {
    if let documentDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as? String {
        let myFilePath = documentDirectory.stringByAppendingPathComponent("MyFolder")
        return NSFileManager.defaultManager().contentsOfDirectoryAtPath(myFilePath, error: nil) as [String]
    }
    return []
}

对于我的txt文件是这样工作的:

let myFileURL = NSBundle.mainBundle().URLForResource("listacomuni", withExtension: "txt")!
let myText = try! String(contentsOfURL: myFileURL, encoding: NSISOLatin1StringEncoding)
print(String(myText))

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