Read and write a String from text file

前端 未结 21 1422
别跟我提以往
别跟我提以往 2020-11-22 00:02

I need to read and write data to/from a text file, but I haven\'t been able to figure out how.

I found this sample code in the Swift\'s iBook, but I still don\'t kno

相关标签:
21条回答
  • 2020-11-22 00:38
     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
    }
    
    0 讨论(0)
  • 2020-11-22 00:39

    Xcode 8.3.2 Swift 3.x. Using NSKeyedArchiver and NSKeyedUnarchiver

    Reading file from documents

    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")
    }
    

    Write file to documents

    NSKeyedArchiver.archiveRootObject(finalDataDict, toFile:(jsonFilePath?.absoluteString)!)
    
    0 讨论(0)
  • 2020-11-22 00:39

    It is recommended to read and write files asynchronously! and it's so easy to do in pure Swift,
    here is the protocol:

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

    As you can see it allows you to read and write files synchronously or asynchronously.

    Here is my implementation in 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)
    }
    
    
    0 讨论(0)
  • 2020-11-22 00:41

    In the function example, (read|write)DocumentsFromFile(...) having some function wrappers certainly seems to makes sense since everything in OSx and iOS seems to need three or four major classes instantiated and a bunch of properties, configured, linked, instantiated, and set, just to write "Hi" to a file, in 182 countries.

    However, these examples aren't complete enough to use in a real program. The write function does not report any errors creating or writing to the file. On the read, I don't think it's a good idea to return an error that the file doesn't exist as the string that is supposed to contain the data that was read. You would want to know that it failed and why, through some notification mechanism, like an exception. Then, you can write some code that outputs what the problem is and allows the user to correct it, or "correctly" breaks the program at that point.

    You would not want to just return a string with an "Error file does not exist" in it. Then, you would have to look for the error in the string from calling function each time and handle it there. You also possibly couldn't really tell if the error string was actually read from an actual file, or if it was produced from your code.

    You can't even call the read like this in swift 2.2 and Xcode 7.3 because NSString(contentsOfFile...) throws an exception. It is a compile time error if you do not have any code to catch it and do something with it, like print it to stdout, or better, an error popup window, or stderr. I have heard that Apple is moving away from try catch and exceptions, but it's going to be a long move and it's not possible to write code without this. I don't know where the &error argument comes from, perhaps an older version, but NSString.writeTo[File|URL] does not currently have an NSError argument. They are defined like this in NSString.h :

    public func writeToURL(url: NSURL, atomically useAuxiliaryFile: Bool, encoding enc: UInt) throws
    public func writeToFile(path: String, atomically useAuxiliaryFile: Bool, encoding enc: UInt) throws
    public convenience init(contentsOfURL url: NSURL, encoding enc: UInt) throws
    public convenience init(contentsOfFile path: String, encoding enc: UInt) throws
    

    Also, the file not existing is just one of a number of potential problems your program might have reading a file, such as a permissions problem, the file size, or numerous other issues that you would not even want to try to code a handler for each one of them. It's best to just assume it's all correct and catch and print, or handle, an exception if something goes amiss, besides, at this point, you don't really have a choice anyway.

    Here are my rewrites :

    func writeToDocumentsFile(fileName:String,value:String) {
    
        let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString!
        let path = documentsPath.stringByAppendingPathComponent(fileName)
    
        do {
            try value.writeToFile(path, atomically: true, encoding: NSUTF8StringEncoding)
        } catch let error as NSError {
            print("ERROR : writing to file \(path) : \(error.localizedDescription)")
        }
    
    }
    
    func readFromDocumentsFile(fileName:String) -> String {
    
        let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
        let path = documentsPath.stringByAppendingPathComponent(fileName)
    
        var readText : String = ""
    
        do {
            try readText = NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding) as String
        }
        catch let error as NSError {
            print("ERROR : reading from file \(fileName) : \(error.localizedDescription)")
        }
        return readText
    }
    
    0 讨论(0)
  • 2020-11-22 00:45

    The current accepted answer above from Adam had some errors for me but here is how I reworked his answer and made this work for me.

    let file = "file.txt"
    
    let dirs: [String]? = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true) as? [String]
    
    if (dirs != nil) {
        let directories:[String] = dirs!
        let dirs = directories[0]; //documents directory
        let path = dirs.stringByAppendingPathComponent(file);
        let text = "some text"
    
        //writing
        text.writeToFile(path, atomically: false, encoding: NSUTF8StringEncoding, error: nil);
    
        //reading
         var error:NSError?
    
        //reading
        let text2 = String(contentsOfFile: path, encoding:NSUTF8StringEncoding, error: &error)
    
        if let theError = error {
            print("\(theError.localizedDescription)")
        }
    }
    
    0 讨论(0)
  • 2020-11-22 00:46

    Latest swift3 code
    You can read data from text file just use bellow code This my text file

         {
    "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)"
               }]
    

    }

    You can use this code you get data from text json file in swift3

         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)
                }
    
    0 讨论(0)
提交回复
热议问题