#swift
#swift
Вопрос:
Я пытаюсь прочитать текстовый файл с помощью Swift playground со следующим
let dirs : String[]? = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true) as? String[]
if (dirs != nil) {
let directories:String[] = dirs!;
let dir = directories[0]; //documents directory
let path = dir.stringByAppendingPathComponent(file);
//read
let content = String.stringWithContentsOfFile(path, encoding: NSUTF8StringEncoding, error: nil)
}
Однако это не удается без ошибок. Кажется, первая строка не позволяет игровой площадке выводить что-либо ниже
Комментарии:
1.
stringWithContentsOfFile
имеет параметр ошибки, проверьте, что он содержит.2. Вы должны использовать условное разворачивание —
if let directories = dirs {
. Сохраняет шаг.
Ответ №1:
Вы также можете поместить свой файл в ресурсы своей игровой площадки. Для этого: покажите навигатор проекта с CMD 1
помощью . Перетащите ваш файл в папку ресурсов. Затем прочитайте файл:
В Xcode 6.4 и Swift 1.2:
var error: NSError?
let fileURL = NSBundle.mainBundle().URLForResource("Input", withExtension: "txt")
let content = String(contentsOfURL: fileURL!, encoding: NSUTF8StringEncoding, error: amp;error)
В Xcode 7 и Swift 2:
let fileURL = NSBundle.mainBundle().URLForResource("Input", withExtension: "txt")
let content = try String(contentsOfURL: fileURL!, encoding: NSUTF8StringEncoding)
В Xcode 8 и Swift 3:
let fileURL = Bundle.main.url(forResource: "Input", withExtension: "txt")
let content = try String(contentsOf: fileURL!, encoding: String.Encoding.utf8)
Если файл содержит двоичные данные, вы можете использовать NSData(contentsOfURL: fileURL!)
или Data(contentsOf: fileURL!)
(для Swift 3).
Ответ №2:
Хотя ответ был предоставлен для быстрого исправления, есть лучшее решение.
Каждый раз, когда игровая площадка открывается, ей будет назначен новый контейнер. Это означает, что при использовании обычной структуры каталогов вам придется каждый раз копировать нужный файл в новый контейнер.
Вместо этого внутри контейнера есть символическая ссылка на общий каталог данных игровой площадки (/Users//Documents/ Shared Playground Data UserName
), который сохраняется при повторном открытии игровой площадки и может быть доступен с нескольких игровых площадок.
Вы можете использовать XCPlayground для доступа к этой общей папке.
import XCPlayground
let path = XCPlaygroundSharedDataDirectoryURL.appendingPathComponent("foo.txt")
Официальную документацию можно найти здесь: Ссылка на модуль XCPlayground
Классный пост о том, как организовать этот каталог для каждой игровой площадки: Swift, Playgrounds и XCPlayground
ОБНОВЛЕНИЕ: для swift 4.2 используйте playgroundSharedDataDirectory. Не нужно ничего импортировать. Похоже:
let path = playgroundSharedDataDirectory.appendingPathComponent("file")
Комментарии:
1. Отличный ответ, потрясающее решение! Мне пришлось создать
~/Documents/Shared Plaground Data
, но после этого все работало так, как ожидалось. Спасибо!2. опечатка в приведенном выше комментарии, но она делает свое дело. Создайте эту папку в documents, поместите туда все, что угодно, и оно будет доступно в XCPSharedDataDirectoryPath
3.
XCPSharedDataDirectoryPath
устарел. Он предлагает использоватьXCPlaygroundSharedDataDirectoryURL
.4. XCode 7.3. Создал
~/Documents/Shared Playground Data
каталог, скопировал туда мой файл, а затем использовал следующий код в Playground:import XCPlayground
вверху иlet path = XCPlaygroundSharedDataDirectoryURL.URLByAppendingPathComponent("myfile.txt")
там, где мне нужно было открыть файл. Обратите внимание, что я пытался использоватьNSData(contentsOfFile:)
, но с вышеизложенным мне просто нужно было переключитьсяNSData(contentsOfURL:)
. Работает как шарм!5. «Для swift 4.2 используйте playgroundSharedDataDirectory. Не нужно ничего импортировать» — вам нужно импортировать PlaygroundSupport (Swift 5 / Xcode 10.2)
Ответ №3:
1. Получите доступ к файлу, который находится в Resources
папке вашей игровой площадки
В Swift 3 Bundle
вызывается метод url(forResource:withExtension:)
. url(forResource:withExtension:)
имеет следующее объявление:
func url(forResource name: String?, withExtension ext: String?) -> URL?
Возвращает URL-адрес файла для ресурса, идентифицируемого указанным именем и расширением файла.
Вы можете использовать url(forResource:withExtension:)
для чтения содержимого файла json, расположенного в Resources
папке игровой площадки iOS или Mac:
import Foundation
do {
guard let fileUrl = Bundle.main.url(forResource: "Data", withExtension: "json") else { fatalError() }
let data = try Data(contentsOf: fileUrl)
let json = try JSONSerialization.jsonObject(with: data, options: [])
print(json)
} catch {
print(error)
}
Вы можете использовать url(forResource:withExtension:)
для чтения содержимого текстового файла, расположенного в Resources
папке Playground для iOS или Mac:
import Foundation
do {
guard let fileUrl = Bundle.main.url(forResource: "Text", withExtension: "txt") else { fatalError() }
let text = try String(contentsOf: fileUrl, encoding: String.Encoding.utf8)
print(text)
} catch {
print(error)
}
В качестве альтернативы let image = UIImage(named: "image")
вы можете использовать url(forResource:withExtension:)
для доступа к изображению, расположенному в Resources
папке iOS Playground:
import UIKit
do {
guard let fileUrl = Bundle.main.url(forResource: "Image", withExtension: "png") else { fatalError() }
let data = try Data(contentsOf: fileUrl)
let image = UIImage(data: data)
} catch {
print(error)
}
2. Получите доступ к файлу, который находится в ~/Documents/Shared Playground Data
папке вашего компьютера
В Swift 3 PlaygroundSupport
модуль предоставляет вызываемую глобальную константу playgroundSharedDataDirectory
. playgroundSharedDataDirectory
имеет следующее объявление:
let playgroundSharedDataDirectory: URL
Путь к каталогу, содержащему данные, общие для всех игровых площадок.
Вы можете использовать playgroundSharedDataDirectory
для чтения содержимого файла json, расположенного в ~/Documents/Shared Playground Data
папке вашего компьютера, с игровой площадки iOS или Mac:
import Foundation
import PlaygroundSupport
do {
let fileUrl = PlaygroundSupport.playgroundSharedDataDirectory.appendingPathComponent("Data.json")
let data = try Data(contentsOf: fileUrl)
let json = try JSONSerialization.jsonObject(with: data, options: [])
print(json)
} catch {
print(error)
}
Вы можете использовать playgroundSharedDataDirectory
для чтения содержимого текстового файла, расположенного в ~/Documents/Shared Playground Data
папке вашего компьютера, с игровой площадки iOS или Mac:
import Foundation
import PlaygroundSupport
do {
let fileUrl = PlaygroundSupport.playgroundSharedDataDirectory.appendingPathComponent("Text.txt")
let text = try String(contentsOf: fileUrl, encoding: String.Encoding.utf8)
print(text)
} catch {
print(error)
}
Вы можете использовать playgroundSharedDataDirectory
для доступа к изображению, расположенному в ~/Documents/Shared Playground Data
папке вашего компьютера, с игровой площадки iOS:
import UIKit
import PlaygroundSupport
do {
let fileUrl = PlaygroundSupport.playgroundSharedDataDirectory.appendingPathComponent("Image.png")
let data = try Data(contentsOf: fileUrl)
let image = UIImage(data: data)
} catch {
print(error)
}
Ответ №4:
Swift 3 (Xcode 8)
Приведенный ниже код работает как на игровых площадках iOS, так и на macOS. Текстовый файл («MyText.txt » в этом примере) должно быть в Resources
каталоге игровой площадки. (Примечание: вам может потребоваться открыть окно навигатора, чтобы увидеть структуру каталогов вашей игровой площадки.)
import Foundation
if let fileURL = Bundle.main.url(forResource:"MyText", withExtension: "txt")
{
do {
let contents = try String(contentsOf: fileURL, encoding: String.Encoding.utf8)
print(contents)
} catch {
print("Error: (error.localizedDescription)")
}
} else {
print("No such file URL.")
}
Ответ №5:
Это работает для меня. Единственное, что я изменил, это указать имя файла (что подразумевается в вашем примере) — возможно, у вас есть опечатка в закадровом определении переменной «file»?
let dirs = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true) as? [String]
let file = "trial.txt" // My change to your code - yours is presumably set off-screen
if let directories = dirs {
let dir = directories[0]; //documents directory
let path = dir.stringByAppendingPathComponent(file);
//read
let content = NSString(contentsOfFile: path, usedEncoding: nil, error: nil)
// works...
}
Обновление Swift 4.2
Как указывает @raistlin, теперь это будет
let dirs = NSSearchPathForDirectoriesInDomains(
FileManager.SearchPathDirectory.documentDirectory,
FileManager.SearchPathDomainMask.userDomainMask,
true)
или, более кратко:
let dirs = NSSearchPathForDirectoriesInDomains(.documentDirectory,
.userDomainMask, true)
Комментарии:
1. Спасибо. Я только что попробовал это на компьютере коллег. Это работает, я использую бета-версию Yosemite, так что, думаю, это моя проблема.
2. да, проблема была в том, что я создал игровую площадку для iOS.
3. Версия Swift 4.2 будет:
NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
Ответ №6:
-
Выберите файл .playground.
-
Откройте Utility inspector, на игровой площадке нажмите opt-cmd-1, чтобы открыть инспектор файлов. Вы должны увидеть игровую площадку справа. Если он не выбран, нажмите cmd-1, чтобы открыть навигатор проекта, и щелкните файл playground.
-
В разделе «Путь к ресурсам» в настройках игровой площадки выберите «Относительно игровой площадки» и платформу как OSX.
Комментарии:
1. Попробуйте изменить платформу в настройках игровой площадки на OSX, это работает только для OSX.
2. Спасибо, похоже, проблема была в платформе, но, похоже, она работала только при создании новой игровой площадки с нуля.
Ответ №7:
В Mavericks with Xcode 6.0.1
вы также можете читать, используя платформу iOS.
import UIKit
let dirs : [String]? = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true) as? [String]
let myDir = "/Shared Playground Data"
let file = "README.md" // My change to your code - yours is presumably set off-screen
if (dirs != nil) {
let directories:[String] = dirs!;
let dir = directories[0] myDir; // iOS playground documents directory
let path = dir.stringByAppendingPathComponent(file);
//read
let content = String.stringWithContentsOfFile(path, encoding: NSUTF8StringEncoding, error: nil)
// works...
println(content!)
}
Помните, вам нужно создать каталог, вызываемый "Shared Playground Data"
в вашем каталоге Documents. В моем случае я использовал эту команду: mkdir "/Users/joao_parana/Documents/Shared Playground Data"
и поместил туда свой файл README.md
Ответ №8:
String.stringWithContentsOfFile УСТАРЕЛ и больше не работает с Xcode 6.1.1
Создайте свой documentDirectoryUrl
let documentDirectoryUrl = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first! as NSURL
Чтобы убедиться, что файл находится там, вы можете использовать команду finder Перейти в папку e скопируйте и вставьте туда распечатанный documentDirectoryUrl.path
println(documentDirectoryUrl.path!)
// should look like this: /Users/userName/Library/Containers/com.apple.dt.playground.stub.OSX.PLAYGROUNDFILENAME-5AF5B25D-D0D1-4B51-A297-00015EE97F13/Data/Documents
Просто добавьте имя файла к URL-адресу папки в качестве компонента пути
let fileNameUrl = documentDirectoryUrl.URLByAppendingPathComponent("ReadMe.txt")
var fileOpenError:NSError?
Проверьте, существует ли файл, прежде чем пытаться его открыть
if NSFileManager.defaultManager().fileExistsAtPath(fileNameUrl.path!) {
if let fileContent = String(contentsOfURL: fileNameUrl, encoding: NSUTF8StringEncoding, error: amp;fileOpenError) {
println(fileContent) // prints ReadMe.txt contents if successful
} else {
if let fileOpenError = fileOpenError {
println(fileOpenError) // Error Domain=NSCocoaErrorDomain Code=XXX "The file “ReadMe.txt” couldn’t be opened because...."
}
}
} else {
println("file not found")
}
Ответ №9:
Я не смог легко прочитать файл в playground и в итоге просто создал command line
приложение в Xcode. Мне показалось, что это сработало для меня очень хорошо.
Ответ №10:
Другие ответы, основанные на «playgroundSharedDataDirectory», никогда не работают для меня, особенно при использовании игровой площадки iOS.
let documentsDirectoryShareURL = PlaygroundSupport.playgroundSharedDataDirectory.absoluteURL
let fileManager = FileManager()
try? fileManager.copyItem(at: URL(fileURLWithPath: "/Users/rufus/Documents/Shared Playground Data/"), to: documentsDirectoryShareURL)
Я просто делаю выше сейчас. Я могу заполнить свою папку documents / shared, и она просто автоматически копируется вручную в каталог документов playgrounds.
Мой код не будет перезаписывать существующие там файлы. Вы могли бы улучшить это, если вам нужно, чтобы просмотреть временные метки файлов, а затем скопировать, если необходимо, и т.д.
Ответ №11:
Swift 5.7.1 — Xcode 14.1
func readFile() -> [String] {
if let fileURL = Bundle.main.url(forResource: "File", withExtension: "txt") {
do {
let content = try String(contentsOf: fileURL)
var x = content.components(separatedBy: "n")
x.removeAll { data in
data.isEmpty
}
return x
} catch {
print(error)
}
}
return [String]()
}
//Usage:
let input = readFile()