Как я могу прочитать файл в Swift playground

#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:

  1. Выберите файл .playground.

  2. Откройте Utility inspector, на игровой площадке нажмите opt-cmd-1, чтобы открыть инспектор файлов. Вы должны увидеть игровую площадку справа. Если он не выбран, нажмите cmd-1, чтобы открыть навигатор проекта, и щелкните файл playground.

  3. В разделе «Путь к ресурсам» в настройках игровой площадки выберите «Относительно игровой площадки» и платформу как 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()