mirror of
https://github.com/apple/swift-nio.git
synced 2026-05-20 20:30:36 +00:00
2550c9ed48
Motivation: NIOFileSystem has a few APIs which expose swift-system. We'll need to replace those before making this API stable. Modifications: - Remove NIOFileSystem product - Modify snippet so that it still builds Result: NIOFileSystem isn't yet public API
104 lines
4.5 KiB
Swift
104 lines
4.5 KiB
Swift
// snippet.hide
|
|
|
|
import NIOCore
|
|
import _NIOFileSystem
|
|
|
|
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
|
|
func main() async throws {
|
|
// snippet.show
|
|
|
|
// NIOFileSystem provides access to the local file system via the FileSystem
|
|
// type which is available as a global shared instance.
|
|
let fileSystem = FileSystem.shared
|
|
|
|
// Files can be inspected by using 'info':
|
|
if let info = try await fileSystem.info(forFileAt: "/Users/hal9000/demise-of-dave.txt") {
|
|
print("demise-of-dave.txt has type '\(info.type)'")
|
|
} else {
|
|
print("demise-of-dave.txt doesn't exist")
|
|
}
|
|
|
|
// Let's find out what's in that file.
|
|
do {
|
|
// Reading a whole file requires a limit. If the file is larger than the limit
|
|
// then an error is thrown. This avoids accidentally consuming too much memory
|
|
// if the file is larger than expected.
|
|
let plan = try await ByteBuffer(
|
|
contentsOf: "/Users/hal9000/demise-of-dave.txt",
|
|
maximumSizeAllowed: .mebibytes(1)
|
|
)
|
|
print("Plan for Dave's demise:", String(decoding: plan.readableBytesView, as: UTF8.self))
|
|
} catch let error as FileSystemError where error.code == .notFound {
|
|
// All errors thrown by the module have type FileSystemError (or
|
|
// Swift.CancellationError). It looks like the file doesn't exist. Let's
|
|
// create it now.
|
|
//
|
|
// The code above for reading the file is shorthand for opening the file in
|
|
// read-only mode and then reading its contents. The FileSystemProtocol
|
|
// has a few different 'withFileHandle' methods for opening a file in different
|
|
// modes. Let's open a file for writing, creating it at the same time.
|
|
try await fileSystem.withFileHandle(
|
|
forWritingAt: "/Users/hal9000/demise-of-dave.txt",
|
|
options: .newFile(replaceExisting: false)
|
|
) { file in
|
|
let plan = ByteBuffer(string: "TODO...")
|
|
try await file.write(contentsOf: plan.readableBytesView, toAbsoluteOffset: 0)
|
|
}
|
|
}
|
|
|
|
// Directories can be opened like regular files but they cannot be read from or
|
|
// written to. However, their contents can be listed:
|
|
let path: FilePath? = try await fileSystem.withDirectoryHandle(atPath: "/Users/hal9000/Music") { directory in
|
|
for try await entry in directory.listContents() {
|
|
if entry.name == "daisy.mp3" {
|
|
// Found it!
|
|
return entry.path
|
|
}
|
|
}
|
|
// No luck.
|
|
return nil
|
|
}
|
|
|
|
if let path = path {
|
|
print("Found file at '\(path)'")
|
|
}
|
|
|
|
// The file system can also be used to perform the following operations on files
|
|
// and directories:
|
|
// - copy,
|
|
// - remove,
|
|
// - rename, and
|
|
// - replace.
|
|
//
|
|
// Here's an example of copying a directory:
|
|
try await fileSystem.copyItem(at: "/Users/hal9000/Music", to: "/Volumes/Tardis/Music")
|
|
|
|
// Symbolic links can also be created (and read with 'destinationOfSymbolicLink(at:)').
|
|
try await fileSystem.createSymbolicLink(at: "/Users/hal9000/Backup", withDestination: "/Volumes/Tardis")
|
|
|
|
// Opening a symbolic link opens its destination so in most cases there's no
|
|
// need to read the destination of a symbolic link:
|
|
try await fileSystem.withDirectoryHandle(atPath: "/Users/hal9000/Backup") { directory in
|
|
// Beyond listing the contents of a directory, the directory handle provides a
|
|
// number of other functions, many of which are also available on regular file
|
|
// handles.
|
|
//
|
|
// This includes getting information about a file, such as its permissions, last access time,
|
|
// and last modification time:
|
|
let info = try await directory.info()
|
|
print("The directory has permissions '\(info.permissions)'")
|
|
|
|
// Where supported, the extended attributes of a file can also be accessed, read, and modified:
|
|
for attribute in try await directory.attributeNames() {
|
|
let value = try await directory.valueForAttribute(attribute)
|
|
print("Extended attribute '\(attribute)' has value '\(value)'")
|
|
}
|
|
|
|
// Once this closure returns the file system will close the directory handle freeing
|
|
// any resources required to access it such as file descriptors. Handles can also be opened
|
|
// with the 'openFile' and 'openDirectory' APIs but that places the onus you to close the
|
|
// handle at an appropriate time to avoid leaking resources.
|
|
}
|
|
// snippet.end
|
|
}
|