Can't access .csv data using MLDataTable - swift

I am trying to read the content of a .csv file using the framework CreateML to read csv data.
Fhe following code generates an error even though the file exists:
let csvURL = URL(fileURLWithPath: "/Volumes/MAC HDD/Data/Data.csv")
let fm = FileManager()
if (fm.fileExists(atPath: csvURL.path)) {
let dataTable = try! MLDataTable(contentsOf: csvURL)
// accessing first column
let col_1 = Array.init(dataTable["col1"])
}
I get the following error message:
Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: CreateML.MLCreateError.generic(reason: "No files corresponding to the specified path (file:///Volumes/MAC%20HDD/Data/Data.csv)")
I have checked nearly everything but can't get any results. What am I doing wrong?

I found out by my self what the problem is.
I have implemented this code in a Xcode project to read csv data, but the CreateML framework is just working for Xcode Playground and not within a Xcode Project! It was mentioned at the end of the WWDC 2018 session video 703.
The code example above is working fine with Xcode Playground.
It would have saved me a lot of time if there had been a warning when importing the framework.

Related

Problem with Firebase Storage reference in Swift program

I am an iOS App developer using Swift. I opened Firebase Storage today and proceeded step by step in accordance with the help document. I can already view the txt file I uploaded on web browser with the url: "https://storage.googleapis.com/my_bucket_name/story_001.txt". But I encountered difficulty in accessing the txt file in the App. I think the problem lies in the generation of the reference. Here is my code:
let ref = Storage.storage().reference();
let txt_ref = ref.child("gs://my_bucket_name").child("story_001.txt");
print(txt_ref.fullPath);
txt_ref.getMetadata{ metadata, error in
if let err = error { print("Failed to get metadata."); }
else{ print("Metadata: \(metadata)"); }
}
I get the following output from console:
gs:/my_bucket_name/story_001.txt
Failed to get metadata.
The two slashes after "gs:" become one slash. I think the problem should come from here.
How can I solve it? Thanks in advance.
You may able to use the reference withPath: API like
let ref = Storage.storage().reference(withPath:"my_bucket_name")
let txt_ref = ref.child("story_001.txt")
See additional examples in these integration tests.

Why is FileHandle inconsistently returning 'nil'

I have an app which is inconsistently returning 'nil' when using FileHandle to open a file for Read. I'm on OSX (10.13.4), XCode 9.4, Swift 4.1
This OSX app uses the NSOpenPanel() to get a list of files selected by the user. My 'model' class code opens these files to build a collection of data structures The code which does this starts out like this and successfully gets a FileHandle EVERY TIME for any file and is able to read data from the file.
private func getFITHeader(filename: String) {
let file: FileHandle? = FileHandle(forReadingAtPath: filename)
if file == nil {
print("FITFile >>> File open failed for file \(filename)")
}
else {
var databuffer: Data
databuffer = (file?.readData(ofLength: 80))!
:
:
}
The files also contain a block of binary data which I process in another part of the app. While I develop the code for this I'm temporarily hard coding one of the same filenames as works above for test purposes. BUT this code (below) ALWAYS throws an exception 'Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value' when it gets to fileHandle?.seek() - for some reason the attempt to create a FileHandle is always returning 'nil' despite the code being functionally identical to tha above.
#IBAction func btnProcFile(_ sender: Any) {
var data: Data
let filename = "/Users/johncneal/Dropbox/JN Astronomy/Astronomy/Spectroscopy/RSpec_Analyses/Gamma_Cas/20161203/Gamma Cas_065.fit"
let fileHandle: FileHandle? = FileHandle(forReadingAtPath: filename)
fileHandle?.seek(toFileOffset: 2880) //skip past the headers
let dataLenToRead = 1391 * 1039 * 2
data = (fileHandle?.readData(ofLength: dataLenToRead))!
:
:
}
The code in the second function works fine in a Playground (not attaching too much meaning to that) and, wierdly, has also worked when temporarily added to a different project. Probably also worth mentioning the length of the file path doesn't seem to matter - it behaves the same on short paths.
So the question is - why is this behaviour of FileHandle reliably inconsistent?
print()'ing the filenames presented to FileHandle() showed they were identical in each case (see below). So I'm stumped and frustrated by this - any perspectives or workarounds would be appreciated.
/Users/johncneal/Dropbox/JN Astronomy/Astronomy/Spectroscopy/RSpec_Analyses/Gamma_Cas/20161203/Gamma Cas_065.fit
/Users/johncneal/Dropbox/JN Astronomy/Astronomy/Spectroscopy/RSpec_Analyses/Gamma_Cas/20161203/Gamma Cas_065.fit
Found the answer - Sandboxing !!
Darren - coincidentally I did look at the URL based route and discovering it 'throws' put some proper error reporting in the catches. Low and behold they reported I didn't have permissions on the file (which initially surprised me since I'm obviously admin on my Mac's and all the files ar local and under my username.
I bit more research turned up. this article - https://forums.developer.apple.com/thread/96062 which quickly revealed its a sandboxing problem :-) Looks like recent versions of XCode have it turned on in 'Entitlements'. The post also points out that the NSOpenPanel FileOpen dialog returns 'Security scoped urls'. At first I thought this explained why the code in the first function worked but I'm not totally convinced because I was only feeding the url.path property to FileHandle.
However, turning off Sandbox in Entitlements makes everything work just fine. Yes, I know thats not the right thing to do longer term (or if I want this to go to the App Store) so I'll be checking out the right way to do this. At least I can get on now - thanks for the input.
The FileHandle initializers are not well named.
You should use FileHandle(forReadingFrom:URL) instead of FileHandle(forReadingAtPath:String). The former is newer API that throws an error instead of returning nil. You can use the thrown error to see why it is failing, and your variables are guaranteed to be non-nil.
For example:
#IBAction func btnProcFile(_ sender: Any) {
do {
let fileUrl = URL(fileURLWithPath:"/Users/johncneal/Dropbox/JN Astronomy/Astronomy/Spectroscopy/RSpec_Analyses/Gamma_Cas/20161203/Gamma Cas_065.fit")
let fileHandle = try FileHandle(forReadingFrom: fileUrl)
fileHandle.seek(toFileOffset: 2880) //skip past the headers
let dataLenToRead = 1391 * 1039 * 2
let data: Data = fileHandle.readData(ofLength: dataLenToRead)
// etc...
} catch let error as NSError {
print("FITFile >>> File open failed: \(error)")
NSApp.presentError(error)
}
}

Swift 4 | Referencing database file for SQLite queries "unable to open database file"

To begin, here is an image of my current project file set-up
I am using the following in this project:
import UIKit
import SQLite
import GRDB
When I execute the following code :
{
tagString = x
let dbQueue = try! DatabaseQueue(path: "data.db" )
try! dbQueue.inDatabase { db in
let rows = try Row.fetchCursor(db, "SELECT * FROM quotes WHERE genre = ? AND LENGTH(quote) < 100",
arguments: [tagString])
I get the following error "unable to open database file" as well as the warning "could not execute support code to read Objective-C class data in the process. This may reduce the quality of type information available."
I have tried changing "data.db" to simlpy "data", but that does not work.
The only solution I have found is when I write the complete path from my computer AND run it on a simulated app. If I try to use the entire path (ex. /Users/myName/Desktop/AppName/data.db) on my phone, the program crashes ( I assume because that memory location does not exist on the phone)
Question: Is my calling of the database correct? If so, any ideas of why It might not be able to find it?
Thankyou.
You get the "unable to open database file" error because you don't specify a valid path to your database.
On iOS, application files must be created at a valid path. Valid paths include paths inside the application's Documents folder. For example:
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
let dbPath = documentsPath.appendingPathComponent("data.db")
let dbQueue = try DatabaseQueue(path: dbPath)
Please refer to the File System Basics chapter of iOS documentation for more information.

What could be a reason for a do try catch issue with contentsOfFile in Swift 3?

I recently converted the syntax of a project I was working on from Swift 2.3 to Swift 3 and am running into some issues with taking the contents of a txt file and converting them into a string. Everything works fine on old txt files in my project but new txt files are failing in the try portion of my code.
I'm not super familiar with how try/catch works but I've tested the code and on files that don't work the catch portion of my code is running so I'm assuming that the try part is failing in those cases. Is this some sort of bug or something that changed in Swift 3? I've checked the new files and they are txt files, formatted exactly the same way as the working txt files so I'm not sure what is wrong.
if let filepath = Bundle.main.path(forResource: fileName, ofType: "txt") {
do {
contents = try String(contentsOfFile: filepath, encoding: String.Encoding.utf8)
print(contents)
textView.text = contents
} catch {
// contents could not be loaded
print(error)
}
} else {
print("No contents found")
}
Error Message with encoding parameter:
Error Domain=NSCocoaErrorDomain Code=261 "The file “35 IAC 14 - Indiana State Teachers' Retirement Fund.txt” couldn’t be opened using text encoding Unicode (UTF-8)." UserInfo={NSFilePath=/Users/graysonfaircloth/Library/Developer/CoreSimulator/Devices/(removed-numbers)/data/Containers/Bundle/Application/(removed-numbers)/CCHA-test-app.app/35 IAC 14 - Indiana State Teachers' Retirement Fund.txt, NSStringEncoding=4}
Error Message without encoding parameter:
Error Domain=NSCocoaErrorDomain Code=264 "The file “35 IAC 14 - Indiana State Teachers' Retirement Fund.txt” couldn’t be opened because the text encoding of its contents can’t be determined." UserInfo={NSFilePath=/Users/graysonfaircloth/Library/Developer/CoreSimulator/Devices/(removed-numbers)/data/Containers/Bundle/Application/(removed-numbers)/CCHA-test-app.app/35 IAC 14 - Indiana State Teachers' Retirement Fund.txt}
In Swift 3 we have extended using throwing, I think it's better then handling error.
You need to check is your file included into build
and check name of file.
Also you can print your path and check manually is your file added to build (simulator).

NSData(contentsOfURL: url) always returning nil

I have this code in a new playground
import Foundation
let blogsURL: NSURL = NSURL(fileURLWithPath: "/Users/Francis/Documents/Xcode_projects/KM registratie/blogs.json")
let data = NSData(contentsOfURL: blogsURL)
On the second line the playground tells me that it (correctly) initialised the URL referring to file:///Users/Francis/Documents/Xcode_projects/KM%20registratie/blogs.json
and on the third line the playground tells me that data is nil
I already googled around but no question seems to be the exact same problem. I found this "NSData contentsOfURL constructor returns nil", but neither restarting Xcode nor restarting my entire computer fixes the problem.
playgrounds are sandboxed and it seems that there isn't an easy way to reach outside their "box". XML parsing in swift the title of this question is a bit misleading, the answer on it does answer this question
It's answered here:
XML parsing in swift
The problem is that your URL isn't pointing where you think it is. You're trying to open a URL in a subdirectory in your sandbox, and it doesn't exist.
You'll need to open the package contents of your playground (right click on the playground and select "Show Package Contents", add a folder called "Resources", and copy your file directly there.
Then you can get the file from the main bundle:
let url: NSURL! = NSBundle.mainBundle().URLForResource("blogs", withExtension: "json")