I'm reading and writing to a text file. There is an instance where I want to delete the contents of the file (but not the file) as a kind of reset. How can I do this?
if ((dirs) != nil) {
var dir = dirs![0]; //documents directory
let path = dir.stringByAppendingPathComponent("UserInfo.txt");
println(path)
let text = "Rondom Text"
//writing
text.writeToFile(path, atomically: false, encoding: NSUTF8StringEncoding, error: nil)
//reading
let text2 = String(contentsOfFile: path, encoding: NSUTF8StringEncoding, error: nil)
println(text2)
Simply write an empty string to the file like this:
let text = ""
text.writeToFile(path, atomically: false, encoding: NSUTF8StringEncoding, error: nil)
If you set up an NSFileHandle, you can use -truncateFileAtOffset:, passing 0 for the offset.
Or, as pointed out in comments, you can simply write an empty string or data to the file.
Or you can use some kind of data structure / database that does not require you to manually truncate files :)
Swift 3.x
let text = ""
do {
try text.write(toFile: fileBundlePath, atomically: false, encoding: .utf8)
} catch {
print(error)
}
Swift 4.x
let text = ""
do {
try text.write(to: filePath, atomically: false, encoding: .utf8)
} catch {
print(error)
}
Related
I am trying to persist a simple file with:
if let documents = directories.first {
if let urlDocuments = URL(string: documents) {
let urlText = urlDocuments.appendingPathComponent("file.txt")
print(urlText)
do {
try text.write(to: urlText, atomically: false, encoding: .utf8)
print(text)
}
catch {}
true)
}
}
but no matter what directory I choose, it saves it in something like
/Users/jaredearl/Library/Developer/CoreSimulator/Devices/6D477D99-7741-472D-8D16-4AE6771AF92E/data/Containers/Data/Appli ... file.txt
That tag there changes across restarts and when I use something like:
let documents = "/Users/jaredearl/Desktop/"
if let urlDocuments = URL(string: documents) {
let urlText = urlDocuments.appendingPathComponent("file.txt")
print(urlText)
do {
try text.write(to: urlText, atomically: false, encoding: .utf8)
print(text)
}
catch {/* error handling here */}
}
Then when I try to read the file I get: NSURLConnection finished with error - code -1002
How can I get it to persist across restarts?
In swift 3.0
You can use same function to read/write in file
func storeSyncLog(txtStor:String) {
let fileName = "a.txt"
let dir = try? FileManager.default.url(for: .documentDirectory,in: .userDomainMask, appropriateFor: nil, create: true)
//If the directory was found, we write a file to it and read it back
if let fileURL = dir?.appendingPathComponent(fileName).appendingPathExtension("txt") {
var inString = ""
do {
inString = try String(contentsOf: fileURL)
} catch {
print("Failed reading from URL: \(fileURL), Error: " + error.localizedDescription)
}
//Write something in file
let outString = inString + "Date:\(Date()) yd : \(txtStor)\n\n"
do {
try outString.write(to: fileURL, atomically: true, encoding: .utf8)
} catch {
print("Failed writing to URL: \(fileURL), Error: " + error.localizedDescription)
}
}
}
Hope its help
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.
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.
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)
}
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)
}
}
A simple solution that works for me. UPDATE, it looks like I must have gotten this from here, so credit where credit is due:
Append text or data to text file in Swift
Usage:
"Hello, world".appendToURL(fileURL: url)
Code:
extension String {
func appendToURL(fileURL: URL) throws {
let data = self.data(using: String.Encoding.utf8)!
try data.append(fileURL: fileURL)
}
}
extension Data {
func append(fileURL: URL) throws {
if let fileHandle = FileHandle(forWritingAtPath: fileURL.path) {
defer {
fileHandle.closeFile()
}
fileHandle.seekToEndOfFile()
fileHandle.write(self)
}
else {
try write(to: fileURL, options: .atomic)
}
}
}
Check the reading part.
The method cotentsOfFile: is a method of NSString class. And you have use it wrong way.
So replace this line
let text2 = String(contentsOfFile: path, encoding: NSUTF8StringEncoding, error: nil)
Here you have to use NSString instead of String class.
let text2 = NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding, error: nil)
I have a plaintext file that simply has a list of words. I’d like to bring this list in as an array but I haven’t had any luck. I can also bring it in as a string and convert it to an array, but I can’t get that to work either.
let location = "/Users/user/Desktop/list.txt"
var content = NSString(contentsOfFile: location, encoding: NSUTF32StringEncoding, error: nil)
println(content)
My output is always “nil". Same thing if I try to do an array instead:
let content2 = NSArray(contentsOfFile: location)
println(content2)
i use this helper class for file working:
class File {
var path=""
init(path: String,name:String){
self.path=path+"/"+name
}
init(path: String){
self.path=path
}
func read()->String {
return NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding, error: nil)!
}
func write(data: String) {
data.writeToFile(path, atomically: true, encoding: NSUTF8StringEncoding, error: nil)
}
func getLineArray()->[String] {
return read().componentsSeparatedByString("\n")
}
}
using:
let address = "/Users/sajadgarshasbi/Desktop/myTestFile/sample.txt"
if NSFileManager.defaultManager().fileExistsAtPath(address) {
let f = File(path: address)
println(f.read())
}else{
println("File Not Found")
}
Does that file exist? What does
NSFileManager().fileExistsAtPath(location)
return?
Also, are you sure it's UTF-32 encoded? The most likely encoding is probably UTF-8.
change:
var content = NSString(contentsOfFile: location, encoding: NSUTF32StringEncoding, error: nil)
to:
var content = NSString(contentsOfFile: location, encoding: NSUTF8StringEncoding, error: &err)
EDIT: removed nil from suggested fix per Martin R's request
If you are using playground it will always return nil because playground is sandboxed. You can place your file inside the documents directory but it is located somewhere else at your computer and probably looks like something like the String below.
"/var/folders/f9/yrxcqv_10m57prx9lwts4qy80000gq/T/com.apple.dt.Xcode.pg/containers/com.apple.dt.playground.stub.iOS_Simulator.MyPlayground-iOS-NSDate-85BEA777-C527-4A79-9B4E-53427CF98B7D/Documents/".
You can open this folder using your finder Main Menu > Go > Go To Folder... (command-shift-G) and paste that directory path there.
You can locate your playground documents folder using the code below:
let documentDirectoryPath = (NSFileManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first as NSURL).path!
Just place your file there and then you can open it as a String:
let fileName = documentDirectoryPath.stringByAppendingPathComponent("test.txt")
var error:NSError?
if "This is a sample sentence.".writeToFile(fileName, atomically: true, encoding: NSUTF8StringEncoding, error: &error) {
println("file successfully saved") // "file successfully saved"
} else {
if let error = error {
println(error.description)
}
}
if let myLoadedString = String(contentsOfFile: fileName, encoding: NSUTF8StringEncoding, error: &error) {
println(myLoadedString) // "This is a sample sentence."
} else {
if let error = error {
println(error.description)
}
}
Is it an easy way to write logs into a text file too? I need a crash log to analyse when something went wrong. But I already use println al around in the code.
Use String.writeToFile(<#path: String#>, atomically: <#Bool#>, encoding: <#NSStringEncoding#>, error: <#NSErrorPointer#>)
You could add this:
#if DEBUG
func println(s:String) {
var error:NSError? = nil
let path = "/Users/<me>/dump.txt"
var dump = String(contentsOfFile: path, encoding: NSUTF8StringEncoding, error: nil)!
"\(dump)\n\(s)".writeToFile(path, atomically:true, encoding:NSUTF8StringEncoding, error:&error)
}
#endif
See the #if DEBUG answer on SO how to use this compiler flag.
For swift 3, change Thomas Killan's code like this
func println(s:String) {
let path = "/Users/<me>/dump.txt"
var dump = ""
if FileManager.default.fileExists(atPath: path) {
dump = try! String(contentsOfFile: path, encoding: String.Encoding.utf8)
}
do {
// Write to the file
try "\(dump)\n\(s)".write(toFile: path, atomically: true, encoding: String.Encoding.utf8)
} catch let error as NSError {
print("Failed writing to log file: \(path), Error: " + error.localizedDescription)
}
}
Unfortunately, using a println()-based solution will not result in output being captured by the Apple System Log (ASL).
The ASL is the logging facility provided by the Mac OS and iOS that is used by NSLog() (and on a Mac is visible through the Console application). Because NSLog() uses ASL, log entries recorded by NSLog() will be visible through the device console. Messages logged through println() will not be captured in ASL, and as a result, provide no opportunity to go back to the console for diagnostic purposes after something has happened.
The CleanroomLogger open-source project provides an extensible Swift API that you can use to do what you want. You would just implement a LogRecorder and specify it in the configuration in addition to the ASLLogRecorder.
I modified a little your function to be global and add to save a log per day.
public func debugPrint(s:String)
{
var paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
let formatter = DateFormatter()
formatter.dateFormat = "dd-MM-yyyy"
let dateString = formatter.string(from: Date())
let fileName = "\(dateString).log"
let logFilePath = (documentsDirectory as NSString).appendingPathComponent(fileName)
var dump = ""
if FileManager.default.fileExists(atPath: logFilePath) {
dump = try! String(contentsOfFile: logFilePath, encoding: String.Encoding.utf8)
}
do {
// Write to the file
try "\(dump)\n\(Date()):\(s)".write(toFile: logFilePath, atomically: true, encoding: String.Encoding.utf8)
} catch let error as NSError {
print("Failed writing to log file: \(logFilePath), Error: " + error.localizedDescription)
}
}
I need to read the contents of a short text file in my Swift program. I did this:
var err: NSError?
let bundle = NSBundle.mainBundle()
let path = bundle.pathForResource("cards", ofType: "ini")
let content = String(contentsOfFile: path!, encoding: NSUTF8StringEncoding, error: nil)
My problem is that I can't use the error reporting. If I change that last line to this:
let content = String(contentsOfFile: path!, encoding: NSUTF8StringEncoding, error: err)
The compiler complains "Extra argument 'contentsOfFile' in call". That makes zero sense to me, maybe someone else can figure it out?
Following the new error handling introduced into iOS 9/Swift 2, a solution for this that works for me is:
let fileLocation = NSBundle.mainBundle().pathForResource("filename", ofType: "txt")!
let text : String
do
{
text = try String(contentsOfFile: fileLocation)
}
catch
{
text = ""
}
text will contain the file contents or be empty in the case of an error.
At a first glance I'd say that you have to pass the err variable by reference:
let content = String(contentsOfFile: path!, encoding: NSUTF8StringEncoding, error: &err)
I was able to resolve the error by using it in this way :
let content = String.stringWithContentsOfFile(path!, encoding: NSUTF8StringEncoding, error: nil)
or if wanted to use error reporting then
var err: NSError?
let content = String.stringWithContentsOfFile(path!, encoding: NSUTF8StringEncoding, error: &err)