Write Data to a file in Caches folder?

I've been struggling for over an hour now trying to figure out what I'm supposed to do in order to write a Data object to a file in the caches folder. This is something I've done hundreds of times in Objective-C over ten years.


Here's how I got the reference to the caches folder:

  let paths = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)
  let cachesDirectory: URL = paths[0]


I then concatenated a filename to it:

let path = "\(cachesDirectory.absoluteString)/foo.json"


I then tried various ways to write the data including the Data.write function, the FileManager createFile function, and also by creating a FileHandle and writing to that. In each case the operation fails with an error that says "No such file or directory foo.json" or something to that effect.


What am I doing wrong?

Replies

Answering my own question, it seems that the expression cachesDirectory.absoluteString does not produce a valid pathname as I was expecting.


I guess that's okay for now, but eventually I'm going to want to inspect the file using the FileManager which I think requires a path.


How do I take a file URL and get the local path out of it?


Thanks,

Frank

Which platform are you using? Regardless, try using the newer URL-based methods to construct the path:


        let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
        let path = cachesDirectory.appendingPathComponent("foo.json")
        print("\(path.absoluteString)")

The property `absoluteString` returns a string representation of URL, for file URLs, it returns a string like "file:...", which cannot be a valid file path.


If you need a file path, you can use `path`:

        let fileManager = FileManager.default
        let urls = fileManager.urls(for: .cachesDirectory, in: .userDomainMask)
        let cachesDirectoryUrl = urls[0]
        let fileUrl = cachesDirectoryUrl.appendingPathComponent("foo.json")
        print(fileUrl.absoluteString) //-> file:///Users/dev/Library/Developer/CoreSimulator/Devices/D456D1E4-0CB4-4CE5-BA19-1FFC3E1D4576/data/Containers/Data/Application/175F94AF-BC12-4159-9EF5-992464640CED/Library/Caches/foo.json
        let filePath = fileUrl.path
        print(filePath) //-> /Users/dev/Library/Developer/CoreSimulator/Devices/D456D1E4-0CB4-4CE5-BA19-1FFC3E1D4576/data/Containers/Data/Application/175F94AF-BC12-4159-9EF5-992464640CED/Library/Caches/foo.json
        if !fileManager.fileExists(atPath: filePath) {
            let contents = Data()
            fileManager.createFile(atPath: filePath, contents: contents)
            print("File \(filePath) created") //-> (On first run)File /Users/dev/Library/Developer/CoreSimulator/Devices/D456D1E4-0CB4-4CE5-BA19-1FFC3E1D4576/data/Containers/Data/Application/175F94AF-BC12-4159-9EF5-992464640CED/Library/Caches/foo.json created
        } else {
            print("File \(filePath) already exists")
        }

Thanks. This helped me write the file, but I'm stuck at the next step.


I now want to determine if the file exists, and if so, get its attributes such as its creation date. Unfortunately, the FileManager class works with paths, not URLs. So I need to somehow convert my file URL into a path.


I am not seeing how to do this. There's a "path" property of the URL, but it doesn't return the file path, in fact it doesn't return anything.


Thanks,

Frank

Did you try what @OOPer posted above? I have always used url.path without any problem, so maybe there is something wrong with your URL. Are you on iOS/macOS (sandboxed?)/etc.? What do print("\(path)") and print("\(path.path)") give you?