Чтение и запись строки в текстовый файл на Swift
Правильное чтение и запись текстовых файлов в Swift
Проблема, с которой вы столкнулись, типична для начинающих разработчиков. Давайте разберёмся по порядку. Главная ошибка — попытка использовать абсолютные пути, которые не работают в песочнице (sandbox) iOS или требуют прав на macOS.
Для iOS (и macOS с sandbox)
Используйте FileManager для получения правильной директории:
import Foundation
// Получаем путь к Documents
guard let documentsDirectory = FileManager.default.urls(
for: .documentDirectory,
in: .userDomainMask
).first else {
fatalError("Не удалось получить Documents directory")
}
let fileURL = documentsDirectory.appendingPathComponent("myFile.txt")
// ЗАПИСЬ
let textToWrite = "Hello, Swift!"
do {
try textToWrite.write(to: fileURL, atomically: true, encoding: .utf8)
print("Файл записан: \(fileURL.path)")
} catch {
print("Ошибка записи: \(error.localizedDescription)")
}
// ЧТЕНИЕ
do {
let readText = try String(contentsOf: fileURL, encoding: .utf8)
print("Прочитано: \(readText)")
} catch {
print("Ошибка чтения: \(error.localizedDescription)")
}
Для macOS (без sandbox, с произвольным путём)
Если вы уверены, что файл существует и у вас есть права:
let path = "/Users/me/Documents/test.txt"
let fileURL = URL(fileURLWithPath: path)
// Запись
let text = "Hello, macOS!"
do {
try text.write(to: fileURL, atomically: true, encoding: .utf8)
} catch {
print("Ошибка: \(error)")
}
// Чтение
do {
let content = try String(contentsOf: fileURL, encoding: .utf8)
print(content)
} catch {
print("Ошибка: \(error)")
}
Ключевые моменты
- URL vs String path: Всегда используйте
URLвместо строки пути — это безопаснее и переносимее. - Песочница (sandbox): На iOS приложение видит только свою директорию Documents. На macOS в песочнице — аналогично.
- Обработка ошибок: Обязательно используйте
do-catchилиtry?для обработки возможных ошибок. - Кодировка: Всегда указывайте
.utf8для совместимости. - atomically: true — гарантирует, что файл не повредится при сбое записи.
Дополнительно: проверка существования файла
let fileManager = FileManager.default
if fileManager.fileExists(atPath: fileURL.path) {
print("Файл существует")
} else {
print("Файла нет, создаём...")
}
Для быстрого прототипирования (playground)
В Xcode Playground можно использовать NSTemporaryDirectory():
let tempDir = NSTemporaryDirectory()
let tempFile = tempDir + "temp.txt"
try? "Test".write(toFile: tempFile, atomically: true, encoding: .utf8)
let result = try? String(contentsOfFile: tempFile)
print(result ?? "nil")
Теперь вы знаете правильный подход. Главное — всегда работать через FileManager и использовать URL.
Альтернативный подход: использование FileHandle и Data
Если вам нужно больше контроля над процессом (например, дописывать в конец файла), используйте FileHandle:
import Foundation
let fileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
.appendingPathComponent("log.txt")
// Запись (создаёт файл, если его нет)
let data = "Новая строка\n".data(using: .utf8)!
FileManager.default.createFile(atPath: fileURL.path, contents: data, attributes: nil)
// Дозапись в конец
if let handle = try? FileHandle(forWritingTo: fileURL) {
handle.seekToEndOfFile()
handle.write(data)
handle.closeFile()
}
// Чтение
if let handle = try? FileHandle(forReadingFrom: fileURL) {
let readData = handle.readDataToEndOfFile()
let text = String(data: readData, encoding: .utf8)
print(text ?? "Ошибка чтения")
handle.closeFile()
}
Этот метод удобен для логов или потоковой записи. Однако для простых операций первый ответ (с write и String(contentsOf:)) предпочтительнее — он короче и понятнее.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги
Зарплаты Java разработчиков в России: обзор рынка — часть 4