[SWIFT] Save files and folders using File Manager

What to write in this article

FileManager allows you to save image, audio and video files to your device. Here I would like to share how to create arbitrary files and folders in the AppData Documents and the folders created there.

スクリーンショット 2021-01-03 23.30.27.jpg

The following sites will be helpful for the folder structure and the roles of each.

About saving iOS app files

Save the text file in Documents

Goal

iOS App
    ├── Documents --- test.txt //Add this
    ├── Library
    │   ├── Caches
    │   └── Preferences
    └── tmp

Source code

func addfile() {
        var documentDirectoryFileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        let filename = "test.txt"
        let path = documentDirectoryFileURL.appendingPathComponent(filename)
        documentDirectoryFileURL = path
        let testText = "This is a pen"
        let data: Data? = testText.data(using: .utf8)
        guard let textFile = data else { return }
        do {
            try textFile.write(to: documentDirectoryFileURL)
            print("Successful")
        } catch {
            print("failed")
        }
    }

flow

When the contents of FileManager.default.urls (for: .documentDirectory, in: .userDomainMask) [0] on the second line are output

file:///var/mobile/Containers/Data/Application/DA078380-F632-4FF0-A96F-F68E036E1B39/Documents/

Will come out. In short, we have prepared a URL type code to go to the Documents folder.

After that, prepare the text file prepared this time as test.txt.

Then, appendingPathComponent changes the URL so that you can go from the Documents folder to the next file.

The sixth line provides the content testText to be saved in the text. Most of the time, I don't think the saved content will be provided in the function saved in the folder, so the part to be changed will be here.

After that, after converting the testText to a data type, write to the folder prepared in the first half.

Save the folder in Documents

Add more folders to the Documents folder.

Goal

iOS App
    ├── Documents --- TestDirectory //Add this
    ├── Library
    │   ├── Caches
    │   └── Preferences
    └── tmp

Source code

func addFolder() {
        let fileManager = FileManager.default
        let documentDirectoryFileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        let directory = documentDirectoryFileURL.appendingPathComponent("TestDirectory", isDirectory: true)
        do {
            try fileManager.createDirectory(at: directory, withIntermediateDirectories: true, attributes: nil)
        } catch {
            print("failed")
        }
    }

flow

The contents up to the third line are duplicated with the contents explained so far, so the explanation is omitted.

The fourth line is appendingPathComponent, which adds the path to Documents. This time I'm adding a folder, not a file, so I've added the isDirectory parameter to make it true.

Then do fileManager.createDirectory and add the folder.

Add files inside the folder you added to Documents

iOS App
    ├── Documents--- TestDirectory --- test.txt  //Add this
    ├── Library
    │   ├── Caches
    │   └── Preferences
    └── tmp

We will mobilize all the knowledge so far.

Source code

I created a function addFolder to add a folder to Document and a function to add a file to the end of the folder added using that function.

func addFolder(_ folderName: String) {
        let fileManager = FileManager.default
        let documentDirectoryFileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        let directory = documentDirectoryFileURL.appendingPathComponent(folderName, isDirectory: true)
        do {
            try fileManager.createDirectory(at: directory, withIntermediateDirectories: true, attributes: nil)
        } catch {
            print("failed")
        }
}

func addfileToFolder(_ folderName: String, _ fileName: String) {
        var pathString = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
        //Add a folder
        addFolder(folderName)
        //Prepare a path
        pathString = "file://" + pathString + "/" + "\(folderName)/"
        guard let path = URL(string: pathString) else { return }
        //Prepare a file to save
        let fileName = "\(fileName).txt"
        let textPath = path.appendingPathComponent(fileName)
    
        //Prepare the contents
        let testText = "This is a pen"
        let data: Data? = testText.data(using: .utf8)
        guard let textFile = data else { return }
        //Write content in the path
        do {
            try textFile.write(to: textPath)
            print("Successful writing")
        } catch let error {
            print("Writing failed\(error)")
        }
}

flow

addFolder

This is made more general by giving a String type argument to addFolder, which adds a folder after Documents mentioned above. Even if a folder with the specified name already existed in Documents, it was not added. (Confirmed)

addfileToFolder

It has the name of the folder to be created at the end of Documents or the path to it, and the name of the file to be added to the end of that folder as arguments.

PathString on the 17th line prepares the path to Documents as Stirng type instead of URL type.

After preparing the folder to save and the path to that point, we are doing the same as before.

Recommended Posts

Save files and folders using File Manager
Delete folders and files with File Manager
Save data from excel file using Rails gem roo
Switched property files for development and production using JMockit
Create environment-independent war file using Maven profiles and maven-war-plugin
[Java] Development with multiple files using package and import
[For myself] Browser display using JSP files and Servlet classes
I tried using Android's open source file download manager Fetch