How to open file and append a string in it, swift
I am trying to append a string into 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 append the string to file. Even if I call this function repeatedly.
Solution 1:
If you want to be able to control whether to append or not, consider using OutputStream
. For example:
do {
let fileURL = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
.appendingPathComponent("votes.txt")
guard let outputStream = OutputStream(url: fileURL, append: true) else {
print("Unable to open file")
return
}
outputStream.open()
let text = "some text\n"
try outputStream.write(text)
outputStream.close()
} catch {
print(error)
}
By the way, this is an extension that lets you easily write a String
(or Data
) to an OutputStream
:
extension OutputStream {
enum OutputStreamError: Error {
case stringConversionFailure
case bufferFailure
case writeFailure
}
/// 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`.
func write(_ string: String, encoding: String.Encoding = .utf8, allowLossyConversion: Bool = false) throws {
guard let data = string.data(using: encoding, allowLossyConversion: allowLossyConversion) else {
throw OutputStreamError.stringConversionFailure
}
try write(data)
}
/// Write `Data` to `OutputStream`
///
/// - parameter data: The `Data` to write.
func write(_ data: Data) throws {
try data.withUnsafeBytes { (buffer: UnsafeRawBufferPointer) throws in
guard var pointer = buffer.baseAddress?.assumingMemoryBound(to: UInt8.self) else {
throw OutputStreamError.bufferFailure
}
var bytesRemaining = buffer.count
while bytesRemaining > 0 {
let bytesWritten = write(pointer, maxLength: bytesRemaining)
if bytesWritten < 0 {
throw OutputStreamError.writeFailure
}
bytesRemaining -= bytesWritten
pointer += bytesWritten
}
}
}
}
For Swift 2 rendition, see previous revision of this answer.
Solution 2:
You can also use FileHandle to append String to your text file. If you just want to append your string the end of your text file just call seekToEndOfFile method, write your string data and just close it when you are done:
FileHandle usage 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)
}
Solution 3:
Please check the below code as its working for me. Just Add the code as it 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)
}
}