Введение в работу с файловой системой в Swift
Разработка под iOS и macOS часто требует взаимодействия с файловой системой устройства. Будь то сохранение пользовательских данных, кэширование изображений или экспорт документов — умение работать с файлами и папками является обязательным навыком для любого Swift-разработчика. В этой статье мы подробно разберем, как использовать FileManager, URL и Data для выполнения всех основных операций с файловой системой.
Мы рассмотрим создание, чтение, запись и удаление файлов, а также навигацию по директориям. Все примеры кода написаны на Swift 5 и подходят как для iOS, так и для macOS проектов.
Основные компоненты: FileManager и URL
В Swift центральным классом для работы с файловой системой является FileManager. Он предоставляет методы для управления файлами, директориями и их атрибутами. Для указания путей используется структура URL, которая является более безопасной и современной альтернативой строкам.
Получение стандартных директорий
Первое, что нужно знать — как получить пути к стандартным системным директориям. Для iOS это обычно Documents, Library/Caches и tmp.
import Foundation
let fileManager = FileManager.default
// Директория Documents
guard let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first else {
fatalError("Не удалось получить Documents директорию")
}
print("Documents: \(documentsURL.path)")
// Директория Caches
guard let cachesURL = fileManager.urls(for: .cachesDirectory, in: .userDomainMask).first else {
fatalError("Не удалось получить Caches директорию")
}
print("Caches: \(cachesURL.path)")
// Временная директория
let tempURL = fileManager.temporaryDirectory
print("Temp: \(tempURL.path)")
Создание и запись файлов
Создание файла в Swift — это комбинация создания пути и записи данных. Рассмотрим два основных подхода.
Запись текстовых данных
func createTextFile() {
guard let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let fileURL = documentsURL.appendingPathComponent("example.txt")
let content = "Привет, мир! Это тестовый файл."
do {
try content.write(to: fileURL, atomically: true, encoding: .utf8)
print("Файл успешно создан по пути: \(fileURL.path)")
} catch {
print("Ошибка записи файла: \(error.localizedDescription)")
}
}
Запись бинарных данных (изображения, архивы)
func createBinaryFile() {
guard let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let fileURL = documentsURL.appendingPathComponent("data.bin")
let data = Data([0x48, 0x65, 0x6C, 0x6C, 0x6F]) // "Hello" в hex
do {
try data.write(to: fileURL, options: .atomic)
print("Бинарный файл создан")
} catch {
print("Ошибка: \(error)")
}
}
Создание директорий
func createDirectory() {
guard let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let newDirURL = documentsURL.appendingPathComponent("MyFolder")
do {
try fileManager.createDirectory(at: newDirURL, withIntermediateDirectories: true, attributes: nil)
print("Директория создана: \(newDirURL.path)")
} catch {
print("Ошибка создания директории: \(error)")
}
}
Чтение и проверка файлов
После того как файлы созданы, их нужно уметь читать и проверять их существование.
Проверка существования файла
func fileExists(at url: URL) -> Bool {
return fileManager.fileExists(atPath: url.path)
}
// Использование
let testURL = documentsURL.appendingPathComponent("example.txt")
if fileExists(at: testURL) {
print("Файл существует")
} else {
print("Файл не найден")
}
Чтение текстового файла
func readTextFile(at url: URL) -> String? {
do {
let content = try String(contentsOf: url, encoding: .utf8)
return content
} catch {
print("Ошибка чтения файла: \(error)")
return nil
}
}
// Пример использования
if let content = readTextFile(at: testURL) {
print("Содержимое файла: \(content)")
}
Чтение бинарных данных
func readBinaryFile(at url: URL) -> Data? {
do {
let data = try Data(contentsOf: url)
return data
} catch {
print("Ошибка чтения бинарного файла: \(error)")
return nil
}
}
Получение списка файлов в директории
func listFilesInDirectory(at url: URL) {
do {
let contents = try fileManager.contentsOfDirectory(at: url, includingPropertiesForKeys: nil, options: .skipsHiddenFiles)
print("Содержимое директории \(url.lastPathComponent):")
for fileURL in contents {
print("- \(fileURL.lastPathComponent)")
}
} catch {
print("Ошибка получения списка файлов: \(error)")
}
}
Перемещение, копирование и удаление файлов
Управление файлами — это не только создание и чтение. Часто требуется перемещать или удалять данные.
Копирование файла
func copyFile(from sourceURL: URL, to destinationURL: URL) {
do {
try fileManager.copyItem(at: sourceURL, to: destinationURL)
print("Файл скопирован в \(destinationURL.path)")
} catch {
print("Ошибка копирования: \(error)")
}
}
Перемещение файла
func moveFile(from sourceURL: URL, to destinationURL: URL) {
do {
try fileManager.moveItem(at: sourceURL, to: destinationURL)
print("Файл перемещен в \(destinationURL.path)")
} catch {
print("Ошибка перемещения: \(error)")
}
}
Удаление файла или директории
func deleteItem(at url: URL) {
do {
try fileManager.removeItem(at: url)
print("Элемент удален: \(url.path)")
} catch {
print("Ошибка удаления: \(error)")
}
}
// Удаление файла
let fileToDelete = documentsURL.appendingPathComponent("example.txt")
deleteItem(at: fileToDelete)
// Удаление директории (вместе со всем содержимым)
let dirToDelete = documentsURL.appendingPathComponent("MyFolder")
deleteItem(at: dir