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)
Related
Swift newbie here. I am trying load a text file into a string using the following code:
var uncondString: String
if let tempstring = try? String(contentsOf: url, encoding: .utf8) {
uncondString = tempstring
}
print("\(uncondString)")
The print statement, however, throws error "Variable 'uncondString' used before being initialized"
I guess this is trivial for more experienced users but any help is appreciated.
If the statement try? fails, it returns nil, and the if let statement is not executed when nil is returned
After all, this code is not a code that unconditionally succeeds in initialization, so a warning is displayed.
var uncondString: String
if let tempstring = try? String(contentsOf: url, encoding: .utf8) {
uncondString = tempstring
print(uncondString)
}
or
let uncondString: String? = try? String(contentsOf: url, encoding: .utf8)
if let uncondStr = uncondString {
print(uncondStr)
}
In the code below, I have removed all other processing in the block.
I am getting an error "fatal error: unexpectedly found nil while unwrapping an Optional value." The error occurs on the line
let webContent = NSString(data: urlContent, encoding: NSUTF8StringEncoding)!
I have determined that the problem is that there is a section symbol in the page. A hex dump of data shows an A7 (so It's not an html tag). If I remove the symbol from the page, the problem goes away. (Unfortunately, I don't have control of the 'live' pages)
How do I keep this error from happening?
let attemptedURL = NSURL(string: "http://www.ilnb.uscourts.gov/sites/all/ajax/calendar.php?mobile=true&judge=\(hearJudge)&start=\(hearDate)&print=true")
print(attemptedURL)
if let url = attemptedURL {
// Create a task to run the web content through
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) -> Void in
if let urlContent = data {
var contThis = true
let webContent = NSString(data: urlContent, encoding: NSUTF8StringEncoding)!
Thank you in advance.
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)
}
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)
}
}