FileManager

The filesystem is a complex topic and how we manipulate it within our applications is generally specific to the operating system that our application is running on. This can be an issue when we are trying to port code from one operating system to another. Apple has addressed this issue by putting the FileManager object in the Core Libraries. The FileManager object lets us examine and make changes to the filesystem in a uniform manner across all operating systems that Swift supports.

The FileManager class provides us with a shared instance that we can use. This instance should be suitable for most of our filesystem-related tasks. We can access this shared instance using the default property.

When we use the FileManager object we can provide paths as an instance of either the URL or String types. In this section, all of our paths will be String types for consistency purposes.

Let's start off by seeing how we could list the contents of a directory using the FileManager object. The following code shows how to do this:

let fileManager = FileManager.default 
 
do { 
  let path = "/Users/jonhoffman/" 
  let dirContents = try fileManager.contentsOfDirectory(atPath: path)  
  for item in dirContents { 
    print(item) 
  } 
} catch let error { 
  print("Failed reading contents of directory: (error)") 
} 

We start off by getting the shared instance of the FileManager object using the default property. We will use this same shared instance for all of our examples in this section rather than redefining it for each example. Next, we define our path and use it with the contentsOfDirectory(atPath:) method. This method returns an array of String types that contains the names of the items in the path. We use a for loop to list these items.

Next, let's look at how we would create a directory using fileManager. The following code shows how to do this:

do { 
  let path = "/Users/jonhoffman/masteringswift/test/dir"  
  try fileManager.createDirectory(atPath: path, 
withIntermediateDirectories: true) } catch let error { print("Failed creating directory, (error) ") }

In this example, we use the createDirectory(atPath: withIntermediateDirectories:) method to create the directory. When we set the withIntermediateDirectories parameter to true, this method will create any parent directories that are missing. When this parameter is set to false, if any parent directories are missing the operation will fail. Now let's look at how we copy an item from one location to another:

do { 
  let pathOrig = "/Users/jonhoffman/masteringswift/"  
  let pathNew = "/Users/jonhoffman/masteringswift2/" 
  try fileManager.copyItem(atPath: pathOrig, toPath: pathNew) 
} catch let error { 
  print("Failed copying directory, (error) ") 
} 

In this example, we use the copyItem(atPath:toPath:) method to copy one item to another location. This method can be used to copy either directories or files. If it is used for directories, the entire path structure below the directory specified by the path is copied. The fileManager also has a method that will let us move an item rather than copying it. Let's see how to do this:

do { 
  let pathOrig = "/Users/jonhoffman/masteringswift2/"  
  let pathNew = "/Users/jonhoffman/masteringswift3/" 
  try fileManager.moveItem(atPath: pathOrig, toPath: pathNew) 
} catch let error { 
  print("Failed moving directory, (error) ") 
} 

To move an item, we use the moveItem(atPath: toPath:) method. Just like the copy example we just saw, the move method can be used for either files or directories. If the path specifies a directory, then the entire directory structure below that path will be moved. Now let's see how we can delete an item from the filesystem:

do { 
  let path = "/Users/jonhoffman/masteringswift/"  
  try fileManager.removeItem(atPath: path) 
} catch let error { 
  print("Failed Removing directory, (error) ") 
} 

In this example, we use the removeItem(atPath:) method to remove the item from the filesystem. A word of warning: once you delete something, it is gone and there is no getting it back.

Next, let's look at how we can read permissions for items in our filesystem. For this, we will need to create a file named test.file, which our path will point to:

let path = "/Users/jonhoffman/masteringswift3/test.file"  
if fileManager.fileExists(atPath: path) { 
  let isReadable = fileManager.isReadableFile(atPath: path)  
  let isWriteable = fileManager.isWritableFile(atPath: path) 
  let isExecutable = fileManager.isExecutableFile(atPath: path)  
  let isDeleteable = fileManager.isDeletableFile(atPath: path)  
  print("can read (isReadable)") 
  print("can write (isWriteable)")  
  print("can execute (isExecutable)")  
  print("can delete (isDeleteable)") 
} 

In this example, we use four different methods to read the filesystem permissions for the filesystem item. These methods are as follows:

  • isReadableFile(atPath:) - true if the file is readable
  • isWritableFile(atPath:) - true if the file is writable
  • isExecutableFile(atPath:) - true if the file is executable
  • isDeletableFile(atPath:) - true if the file is deletable

If we wanted to read or write text files, we could use methods provided by the String type, rather than the FileManager type. Even though we do not use the FileManager class for this example, we wanted to show how to read and write text files. Let's see how we would write some text to a file:

let filePath = "/Users/jonhoffman/Documents/test.file"  
let outString = "Write this text to the file" 
do { 
  try outString.write(toFile: filePath, atomically: true, encoding: .utf8) 
} catch let error { 
  print("Failed writing to path: (error)") 
} 

In this example, we start off by defining our path as a String type just as we did in the previous examples. We then create another instance of the String type that contains the text we want to put in our file. To write the text to the file, we use the write(toFile: atomically: encoding:) method of the String instance. This method will create the file if needed and write the contents of the String instance to the file. It is just as easy to read a text file using the String type. The following example shows how to do this:

let filePath = "/Users/jonhoffman/Documents/test.file"
var inString = "" do { inString = try String(contentsOfFile: filePath) } catch let error { print("Failed reading from path: (error)") } print("Text Read: (inString)")

In this example, we use the contentsOfFile: initiator to create an instance of the String type that contains the contents of the file specified by the file path. Now that we have seen how to use the FileManager type, let's look at how to serialize and deserialize JSON documents using encoding and decoding.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset