How to open a file and add a line to it, swift

I am trying to add a line to a text file. I am using the following code.

let dirs : [String]? = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true) as? [String] if (dirs) != nil { let dir = dirs![0] //documents directory let path = dir.stringByAppendingPathComponent("votes") let text = "some text" //writing text.writeToFile(path, atomically: true, encoding: NSUTF8StringEncoding, error: nil) //reading let text2 = String(contentsOfFile: path, encoding: NSUTF8StringEncoding, error: nil) println(text2) //prints some text } 

this does not add a line to the file. Even if I call this function several times.

+5
source share
5 answers

If you want to be able to control whether to add or not, consider using an OutputStream . For instance:

SWIFT 3

 let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) .appendingPathComponent("votes.txt") if let outputStream = OutputStream(url: fileURL, append: true) { outputStream.open() let text = "some text\n" let bytesWritten = outputStream.write(text) if bytesWritten < 0 { print("write failure") } outputStream.close() } else { print("Unable to open file") } 

By the way, this is an extension that allows you to easily write a String to an OutputStream :

 extension OutputStream { /// Write `String` to `OutputStream` /// /// - parameter string: The `String` to write. /// - parameter encoding: The `String.Encoding` to use when writing the string. This will default to `.utf8`. /// - parameter allowLossyConversion: Whether to permit lossy conversion when writing the string. Defaults to `false`. /// /// - returns: Return total number of bytes written upon success. Return `-1` upon failure. func write(_ string: String, encoding: String.Encoding = .utf8, allowLossyConversion: Bool = false) -> Int { if let data = string.data(using: encoding, allowLossyConversion: allowLossyConversion) { return data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> Int in var pointer = bytes var bytesRemaining = data.count var totalBytesWritten = 0 while bytesRemaining > 0 { let bytesWritten = self.write(pointer, maxLength: bytesRemaining) if bytesWritten < 0 { return -1 } bytesRemaining -= bytesWritten pointer += bytesWritten totalBytesWritten += bytesWritten } return totalBytesWritten } } return -1 } } 

Or, in Swift 2, use NSOutputStream :

 let documents = try! NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false) let path = documents.URLByAppendingPathComponent("votes").path! if let outputStream = NSOutputStream(toFileAtPath: path, append: true) { outputStream.open() let text = "some text" outputStream.write(text) outputStream.close() } else { print("Unable to open file") } 

and

 extension NSOutputStream { /// Write `String` to `NSOutputStream` /// /// - parameter string: The string to write. /// - parameter encoding: The NSStringEncoding to use when writing the string. This will default to UTF8. /// - parameter allowLossyConversion: Whether to permit lossy conversion when writing the string. Defaults to `false`. /// /// - returns: Return total number of bytes written upon success. Return -1 upon failure. func write(string: String, encoding: NSStringEncoding = NSUTF8StringEncoding, allowLossyConversion: Bool = false) -> Int { if let data = string.dataUsingEncoding(encoding, allowLossyConversion: allowLossyConversion) { var bytes = UnsafePointer<UInt8>(data.bytes) var bytesRemaining = data.length var totalBytesWritten = 0 while bytesRemaining > 0 { let bytesWritten = self.write(bytes, maxLength: bytesRemaining) if bytesWritten < 0 { return -1 } bytesRemaining -= bytesWritten bytes += bytesWritten totalBytesWritten += bytesWritten } return totalBytesWritten } return -1 } } 
+20
source

You can also use FileHandle to add String to a text file. If you just want to add a line to the end of the text file, just call the seekToEndOfFile method, write the string data and just close it when you are done


Using FileHandle Swift 3 or later

 let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! // create a new text file at your documents directory or use an existing text file resource url let fileURL = documentsDirectory.appendingPathComponent("simpleText.txt") do { try Data("Hello World\n".utf8).write(to: fileURL) } catch { print(error) } // open your text file and set the file pointer at the end of it do { let fileHandle = try FileHandle(forWritingTo: fileURL) fileHandle.seekToEndOfFile() // convert your string to data or load it from another resource let str = "Line 1\nLine 2\n" let textData = Data(str.utf8) // append your text to your text file fileHandle.write(textData) // close it when done fileHandle.closeFile() // testing/reading the file edited if let text = try? String(contentsOf: fileURL, encoding: .utf8) { print(text) // "Hello World\nLine 1\nLine 2\n\n" } } catch { print(error) } 
+2
source

Please check the code below as it works for me. Just add the code as is:

 let theDocumetFolderSavingFiles = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String let filePath = "/theUserData.txt" let thePathToFile = theDocumetFolderSavingFiles.stringByAppendingString(filePath) let theFileManager = NSFileManager.defaultManager() if(theFileManager.fileExistsAtPath(thePathToFile)){ do { let stringToStore = "Hello working fine" try stringToStore.writeToFile(thePathToFile, atomically: true, encoding: NSUTF8StringEncoding) }catch let error as NSError { print("we are geting exception\(error.domain)") } do{ let fetchResult = try NSString(contentsOfFile: thePathToFile, encoding: NSUTF8StringEncoding) print("The Result is:-- \(fetchResult)") }catch let errorFound as NSError{ print("\(errorFound)") } }else { // Code to Delete file if existing do{ try theFileManager.removeItemAtPath(thePathToFile) }catch let erorFound as NSError{ print(erorFound) } } 
+1
source

Check out the reading part.

The cotentsOfFile: method is a method of the NSString class. And you used it wrong.

So replace this line

 let text2 = String(contentsOfFile: path, encoding: NSUTF8StringEncoding, error: nil) 

Here you should use NSString instead of the String class.

 let text2 = NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding, error: nil) 
0
source

I am using the OutputStream extension in a project. But after upgrading to Swift 5.0, it does not work.

This is adapted code now. But I have a pointer problem.


OutputStream extension {

 func write(_ string: String, encoding: String.Encoding = .utf8, allowLossyConversion: Bool = false) -> Int { if let data = string.data(using: encoding, allowLossyConversion: allowLossyConversion) { //return data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> Int in //until Swift4.2 return data.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) -> Int in //var pointer = bytes //until Swift4.2 var pointer = bytes.bindMemory(to: UInt8.self) var bytesRemaining = data.count var totalBytesWritten = 0 while bytesRemaining > 0 { //let bytesWritten = self.write(pointer, maxLength: bytesRemaining) //until Swift4.2 let bytesWritten = self.write(pointer.baseAddress!, maxLength: bytesRemaining) if bytesWritten < 0 { return -1 } bytesRemaining -= bytesWritten //pointer += bytesWritten //until Swift4.2 

// this is my problem right now !! How to solve the following line ???: pointer = pointer.baseAddress! + bytesWritten

  totalBytesWritten += bytesWritten } return totalBytesWritten } } return -1 } 

}

Regards, Werner

0
source

Source: https://habr.com/ru/post/1207102/


All Articles