Работа с файловой системой в Swift: Полное руководство
Управление файлами и директориями — одна из ключевых задач при разработке приложений для iOS и macOS. В Swift основным инструментом для работы с файловой системой является класс FileManager. В этой статье мы разберём, как создавать, читать, записывать, перемещать и удалять файлы, а также как эффективно управлять директориями. Все примеры кода написаны на Swift и подходят для проектов под iOS и macOS.
Основы FileManager
FileManager — это синглтон, предоставляющий интерфейс для взаимодействия с файловой системой. Для его использования достаточно получить экземпляр:
let fileManager = FileManager.default
Класс позволяет выполнять практически любые операции: проверять существование файлов, получать атрибуты, создавать папки и многое другое. Важно помнить, что все операции по работе с файловой системой могут выбрасывать ошибки, поэтому мы будем использовать конструкцию do-catch.
Работа с директориями
Прежде чем создавать файлы, нужно научиться управлять папками. Рассмотрим основные операции с директориями.
Проверка существования директории
let documentsPath = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
let newFolderPath = documentsPath.appendingPathComponent("MyFolder")
if fileManager.fileExists(atPath: newFolderPath.path) {
print("Директория существует")
} else {
print("Директория не найдена")
}
Создание директории
do {
try fileManager.createDirectory(at: newFolderPath,
withIntermediateDirectories: true,
attributes: nil)
print("Директория создана")
} catch {
print("Ошибка создания директории: \(error.localizedDescription)")
}
Параметр withIntermediateDirectories позволяет автоматически создавать все недостающие папки по пути. Например, если вы хотите создать Folder1/Folder2/Folder3, а Folder1 не существует — он будет создан автоматически.
Получение списка содержимого директории
do {
let contents = try fileManager.contentsOfDirectory(at: documentsPath,
includingPropertiesForKeys: nil)
for item in contents {
print("Найден элемент: \(item.lastPathComponent)")
}
} catch {
print("Ошибка чтения директории: \(error)")
}
Чтение и запись файлов
В Swift существует несколько способов записи и чтения данных. Рассмотрим основные из них.
Запись текстового файла
let text = "Привет, мир! Это тестовый файл."
let filePath = documentsPath.appendingPathComponent("test.txt")
do {
try text.write(to: filePath, atomically: true, encoding: .utf8)
print("Файл успешно записан")
} catch {
print("Ошибка записи: \(error)")
}
Чтение текстового файла
do {
let savedText = try String(contentsOf: filePath, encoding: .utf8)
print("Содержимое файла: \(savedText)")
} catch {
print("Ошибка чтения: \(error)")
}
Работа с бинарными данными
// Запись
let data = "Binary data example".data(using: .utf8)!
let binaryPath = documentsPath.appendingPathComponent("data.bin")
do {
try data.write(to: binaryPath, options: .atomic)
print("Бинарные данные записаны")
} catch {
print("Ошибка записи данных: \(error)")
}
// Чтение
do {
let loadedData = try Data(contentsOf: binaryPath)
print("Прочитано \(loadedData.count) байт")
} catch {
print("Ошибка чтения данных: \(error)")
}
Перемещение, копирование и удаление файлов
Управление файлами включает не только создание, но и перемещение, копирование и удаление.
Копирование файла
let sourcePath = documentsPath.appendingPathComponent("test.txt")
let destinationPath = documentsPath.appendingPathComponent("copy_test.txt")
do {
try fileManager.copyItem(at: sourcePath, to: destinationPath)
print("Файл скопирован")
} catch {
print("Ошибка копирования: \(error)")
}
Перемещение (переименование) файла
let newNamePath = documentsPath.appendingPathComponent("renamed_test.txt")
do {
try fileManager.moveItem(at: sourcePath, to: newNamePath)
print("Файл перемещён/переименован")
} catch {
print("Ошибка перемещения: \(error)")
}
Удаление файла или директории
do {
try fileManager.removeItem(at: newNamePath)
print("Файл удалён")
} catch {
print("Ошибка удаления: \(error)")
}
Важно: Удаление — необратимая операция. Всегда проверяйте существование файла перед удалением и используйте дополнительные подтверждения в пользовательском интерфейсе.
Работа с атрибутами файлов
FileManager позволяет получать и изменять атрибуты файлов — размер, дату создания, права доступа и другие.
let filePath = documentsPath.appendingPathComponent("test.txt")
do {
let attributes = try fileManager.attributesOfItem(atPath: filePath.path)
if let fileSize = attributes[.size] as? NSNumber {
print("Размер файла: \(fileSize.intValue) байт")
}
if let creationDate = attributes[.creationDate] as? Date {
print("Дата создания: \(creationDate)")
}
if let modificationDate = attributes[.modificationDate] as? Date {
print("Дата изменения: \(modificationDate)")
}
if let fileType = attributes[.type] as? FileAttributeType {
print("Тип файла: \(fileType == .typeRegular ? "Обычный" : "Директория")")
}
} catch {
print("Ошибка получения атрибутов: \(error)")
}
Обработка ошибок и безопасность
При работе с файловой системой всегда используйте do-catch для обработки ошибок. Типичные ошибки:
- NSFileNoSuchFileError — файл не существует
- NSFileWriteOutOfSpaceError — недостаточно места на диске
- NSFileWritePermissionError — недостаточно прав для записи
- NSFileReadNoSuchFileError — попытка чтения несуществующего файла
Пример безопасного удаления файла с проверкой:
func safeDeleteFile(at path: URL) {
guard fileManager.fileExists(atPath