Leia e escreva uma String a partir do arquivo de texto

298

Preciso ler e gravar dados de / para um arquivo de texto, mas não consegui descobrir como.

Encontrei esse código de amostra no iBook do Swift, mas ainda não sei como escrever ou ler dados.

import Cocoa

class DataImporter
{
    /*
    DataImporter is a class to import data from an external file.
    The class is assumed to take a non-trivial amount of time to initialize.
    */
    var fileName = "data.txt"
    // the DataImporter class would provide data importing functionality here
}

class DataManager
{
    @lazy var importer = DataImporter()
    var data = String[]()
    // the DataManager class would provide data management functionality here
}

let manager = DataManager()
manager.data += "Some data"
manager.data += "Some more data"
// the DataImporter instance for the importer property has not yet been created”

println(manager.importer.fileName)
// the DataImporter instance for the importer property has now been created
// prints "data.txt”



var str = "Hello World in Swift Language."
Jorge Vega Sánchez
fonte

Respostas:

547

Para ler e escrever, você deve usar um local gravável, por exemplo, diretório de documentos. O código a seguir mostra como ler e escrever uma sequência simples. Você pode testá-lo em um playground.

Swift 3.x - 5.x

let file = "file.txt" //this is the file. we will write to and read from it

let text = "some text" //just a text

if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {

    let fileURL = dir.appendingPathComponent(file)

    //writing
    do {
        try text.write(to: fileURL, atomically: false, encoding: .utf8)
    }
    catch {/* error handling here */}

    //reading
    do {
        let text2 = try String(contentsOf: fileURL, encoding: .utf8)
    }
    catch {/* error handling here */}
}

Swift 2.2

let file = "file.txt" //this is the file. we will write to and read from it

let text = "some text" //just a text

if let dir = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true).first {
    let path = NSURL(fileURLWithPath: dir).URLByAppendingPathComponent(file)

    //writing
    do {
        try text.writeToURL(path, atomically: false, encoding: NSUTF8StringEncoding)
    }
    catch {/* error handling here */}

    //reading
    do {
        let text2 = try NSString(contentsOfURL: path, encoding: NSUTF8StringEncoding)
    }
    catch {/* error handling here */}
}

Swift 1.x

let file = "file.txt"

if let dirs : [String] = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true) as? [String] {
    let dir = dirs[0] //documents directory
    let path = dir.stringByAppendingPathComponent(file);
    let text = "some text"

    //writing
    text.writeToFile(path, atomically: false, encoding: NSUTF8StringEncoding, error: nil);

    //reading
    let text2 = String(contentsOfFile: path, encoding: NSUTF8StringEncoding, error: nil)
}
Adão
fonte
2
// text2 = String.stringWithContentsOfFile (path) // XCode 6.0
Matt Frear
Usar esta solução funciona, mas se eu abrir o arquivo, não haverá texto nele. Estou faltando alguma coisa?
Nuno Gonçalves
@ Adam O que é esse arquivo em let path = dir.stringByAppendingPathComponent (file) ;?
Zbz.lvlv
7
Isso deve ser removido, o código não funciona para novas versões do Swift.
1
@ billy_b29 O código após esta linha: //readingfaz exatamente isso.
Adam
88

Supondo que você moveu seu arquivo de texto data.txtpara o seu projeto Xcode (use drag'n'drop e marque "Copiar arquivos se necessário"), você pode fazer o seguinte, como no Objective-C:

let bundle = NSBundle.mainBundle()
let path = bundle.pathForResource("data", ofType: "txt")        
let content = NSString.stringWithContentsOfFile(path) as String

println(content) // prints the content of data.txt

Atualização:
para ler um arquivo do Bundle (iOS), você pode usar:

let path = NSBundle.mainBundle().pathForResource("FileName", ofType: "txt")
var text = String(contentsOfFile: path!, encoding: NSUTF8StringEncoding, error: nil)!
println(text)

Atualização para o Swift 3:

let path = Bundle.main.path(forResource: "data", ofType: "txt") // file path for file "data.txt"
var text = String(contentsOfFile: path!, encoding: NSUTF8StringEncoding, error: nil)!

Para Swift 5

let path = Bundle.main.path(forResource: "ListAlertJson", ofType: "txt") // file path for file "data.txt"
let string = try String(contentsOfFile: path!, encoding: String.Encoding.utf8)
wottpal
fonte
3
Para projetos iOS, "stringWithContentsOfFile" não está disponível (obsoleto a partir do iOS 7)
alttag
1
Nada a ver com projets iOS, ele é obsoleto e não funciona mais com o Xcode 6.1 (incluindo Mac OS X)
Leo Dabus
1
você pode usar String (contentsOfFile: ...)
shim
1
feixe uso solução semelhante com iOS 10 Swift 3 aqui
Eterna
69

Xcode 8.x • Swift 3.x ou posterior

do {
    // get the documents folder url
    if let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
        // create the destination url for the text file to be saved
        let fileURL = documentDirectory.appendingPathComponent("file.txt")
        // define the string/text to be saved
        let text = "Hello World !!!"
        // writing to disk 
        // Note: if you set atomically to true it will overwrite the file if it exists without a warning
        try text.write(to: fileURL, atomically: false, encoding: .utf8)
        print("saving was successful")
        // any posterior code goes here
        // reading from disk
        let savedText = try String(contentsOf: fileURL)
        print("savedText:", savedText)   // "Hello World !!!\n"
    }
} catch {
    print("error:", error)
}
Leo Dabus
fonte
O que é os erros mais comuns de "Não existe esse arquivo". Como adicionei meus arquivos .txt ao navegador de projetos e, em seguida, tento abri-los, recebo esta mensagem. (Criar-los no ambiente de trabalho e os arrastaram para navegador do projeto)
Darvydas
56

Novo método mais simples e recomendado: a Apple recomenda o uso de URLs para manipulação de arquivos e as outras soluções aqui parecem obsoletas (veja os comentários abaixo). A seguir, é apresentada a nova maneira simples de ler e escrever com URLs (não se esqueça de lidar com os possíveis erros de URL):

Swift 5+, 4 e 3.1

import Foundation  // Needed for those pasting into Playground

let fileName = "Test"
let dir = try? FileManager.default.url(for: .documentDirectory, 
      in: .userDomainMask, appropriateFor: nil, create: true)

// If the directory was found, we write a file to it and read it back
if let fileURL = dir?.appendingPathComponent(fileName).appendingPathExtension("txt") {

    // Write to the file named Test
    let outString = "Write this text to the file"
    do {
        try outString.write(to: fileURL, atomically: true, encoding: .utf8)
    } catch {
        print("Failed writing to URL: \(fileURL), Error: " + error.localizedDescription)
    }

    // Then reading it back from the file
    var inString = ""
    do {
        inString = try String(contentsOf: fileURL)
    } catch {
        print("Failed reading from URL: \(fileURL), Error: " + error.localizedDescription)
    }
    print("Read from the file: \(inString)")
}
Sverrisson
fonte
1
Você pode fornecer uma referência onde a Apple recomenda dessa maneira. Ou você pode elaborar um pouco mais sobre por que essa é a maneira recomendada?
Andrej
6
@Andrej "Objetos de URL são a maneira preferida de se referir a arquivos locais. A maioria dos objetos que lê ou grava dados em um arquivo tem métodos que aceitam um objeto NSURL em vez de um nome de caminho como referência de arquivo." developer.apple.com/library/ios/documentation/Cocoa/Reference/…
Sverrisson 9/16
1
Você não precisa converter os erros como NSError ou usar "catch let error". Você pode simplesmente pegar e obter a variável de erro gratuitamente.
cuomo456
@ cuomo456 à sua direita Eu removo, é uma sobra da versão anterior do Swift beta.
Sverrisson
1
@Alshcompiler Criar: verdadeiros informa FileManager para criar o diretório se ele não estiver lá, em vez de falhar
Sverrisson
28

Xcode 8, Swift 3 maneira de ler o arquivo do pacote de aplicativos:

if let path = Bundle.main.path(forResource: filename, ofType: nil) {
    do {
        let text = try String(contentsOfFile: path, encoding: String.Encoding.utf8)
        print(text)
    } catch {
        printError("Failed to read text from \(filename)")
    }
} else {
    printError("Failed to load file from app bundle \(filename)")
} 

Aqui está uma conveniente extensão de copiar e colar

public extension String {
    func contentsOrBlank()->String {
        if let path = Bundle.main.path(forResource:self , ofType: nil) {
            do {
                let text = try String(contentsOfFile:path, encoding: String.Encoding.utf8)
                return text
                } catch { print("Failed to read text from bundle file \(self)") }
        } else { print("Failed to load file from bundle \(self)") }
        return ""
    }
    }

Por exemplo

let t = "yourFile.txt".contentsOrBlank()

Você quase sempre deseja uma matriz de linhas:

let r:[String] = "yourFile.txt"
     .contentsOrBlank()
     .characters
     .split(separator: "\n", omittingEmptySubsequences:ignore)
     .map(String.init)
Crashalot
fonte
2
Eu colei em uma extensão útil @crashalot - sinta-se livre para excluir,
saúde
1
@Alshcompiler NO! Você não pode ESCREVER um arquivo no pacote.
Sverrisson
Eu estava falando sobre a leitura do arquivo, ele é a única resposta que trabalhou comigo se o arquivo está em arquivos de projeto
Alsh compilador
10

Quero mostrar apenas a primeira parte, que é lida . Veja como você pode simplesmente ler:

Swift 3:

let s = try String(contentsOfFile: Bundle.main.path(forResource: "myFile", ofType: "txt")!)

Swift 2:

let s = try! String(contentsOfFile: NSBundle.mainBundle().pathForResource("myFile", ofType: "txt")!)
AKM Tariqul Islam
fonte
5

Maneira mais simples de ler um arquivo no Swift> 4.0

 let path = Bundle.main.path(forResource: "data", ofType: "txt") // file path for file "data.txt"
        do {
            var text = try String(contentsOfFile: path!)
        }
        catch(_){print("error")}
    }
iosMentalist
fonte
3

A resposta atual aceita acima de Adam teve alguns erros para mim, mas aqui está como refiz a resposta dele e fiz esse trabalho para mim.

let file = "file.txt"

let dirs: [String]? = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true) as? [String]

if (dirs != nil) {
    let directories:[String] = dirs!
    let dirs = directories[0]; //documents directory
    let path = dirs.stringByAppendingPathComponent(file);
    let text = "some text"

    //writing
    text.writeToFile(path, atomically: false, encoding: NSUTF8StringEncoding, error: nil);

    //reading
     var error:NSError?

    //reading
    let text2 = String(contentsOfFile: path, encoding:NSUTF8StringEncoding, error: &error)

    if let theError = error {
        print("\(theError.localizedDescription)")
    }
}
DCorrigan
fonte
3

Você pode achar essa ferramenta útil não apenas para ler arquivos no Swift, mas também para analisar sua entrada: https://github.com/shoumikhin/StreamScanner

Basta especificar o caminho do arquivo e os delimitadores de dados como este:

import StreamScanner

if let input = NSFileHandle(forReadingAtPath: "/file/path")
{
    let scanner = StreamScanner(source: input, delimiters: NSCharacterSet(charactersInString: ":\n"))  //separate data by colons and newlines

    while let field: String = scanner.read()
    {
        //use field
    }
}

Espero que isto ajude.

shoumikhin
fonte
2

Eu tive que recodificar assim:

let path = NSBundle.mainBundle().pathForResource("Output_5", ofType: "xml")
let text = try? NSString(contentsOfFile: path! as String, encoding: NSUTF8StringEncoding)
print(text)
Nagarjun
fonte
2

No exemplo de função, (ler | escrever) DocumentsFromFile (...) ter alguns wrappers de função certamente parece fazer sentido, pois tudo no OSx e iOS parece precisar de três ou quatro classes principais instanciadas e um monte de propriedades, configuradas, vinculadas, instanciado e definido apenas para escrever "Oi" em um arquivo, em 182 países.

No entanto, esses exemplos não são completos o suficiente para serem usados ​​em um programa real. A função de gravação não relata erros ao criar ou gravar no arquivo. Na leitura, não acho uma boa ideia retornar um erro de que o arquivo não existe como a sequência que deveria conter os dados lidos. Você gostaria de saber que ela falhou e por que, através de algum mecanismo de notificação, como uma exceção. Em seguida, você pode escrever um código que mostre qual é o problema e permita que o usuário o corrija ou que "corretamente" interrompa o programa nesse momento.

Você não gostaria apenas de retornar uma string com um "arquivo de erro não existe". Em seguida, você teria que procurar o erro na sequência de chamada da função a cada vez e manipulá-la lá. Você também não pode realmente dizer se a sequência de erros foi realmente lida em um arquivo real ou se foi produzida a partir do seu código.

Você não pode nem chamar a leitura assim no swift 2.2 e no Xcode 7.3 porque o NSString (contentsOfFile ...) lança uma exceção. É um erro de tempo de compilação se você não tiver nenhum código para capturá-lo e fazer algo com ele, como imprimi-lo no stdout, ou melhor, em uma janela pop-up de erro ou stderr. Ouvi dizer que a Apple está se afastando do try catch e das exceções, mas será uma mudança longa e não é possível escrever código sem isso. Não sei de onde vem o argumento & error, talvez uma versão mais antiga, mas o NSString.writeTo [File | URL] não possui atualmente um argumento NSError. Eles são definidos assim no NSString.h:

public func writeToURL(url: NSURL, atomically useAuxiliaryFile: Bool, encoding enc: UInt) throws
public func writeToFile(path: String, atomically useAuxiliaryFile: Bool, encoding enc: UInt) throws
public convenience init(contentsOfURL url: NSURL, encoding enc: UInt) throws
public convenience init(contentsOfFile path: String, encoding enc: UInt) throws

Além disso, o arquivo não existente é apenas um dos vários problemas em potencial que seu programa pode ter ao ler um arquivo, como um problema de permissões, o tamanho do arquivo ou vários outros problemas que você nem gostaria de tentar codificar para um manipulador. cada um deles. É melhor presumir que está tudo correto e capturar e imprimir, ou manipular, uma exceção se algo der errado, além disso, neste momento, você realmente não tem escolha.

Aqui estão minhas reescritas:

func writeToDocumentsFile(fileName:String,value:String) {

    let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString!
    let path = documentsPath.stringByAppendingPathComponent(fileName)

    do {
        try value.writeToFile(path, atomically: true, encoding: NSUTF8StringEncoding)
    } catch let error as NSError {
        print("ERROR : writing to file \(path) : \(error.localizedDescription)")
    }

}

func readFromDocumentsFile(fileName:String) -> String {

    let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
    let path = documentsPath.stringByAppendingPathComponent(fileName)

    var readText : String = ""

    do {
        try readText = NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding) as String
    }
    catch let error as NSError {
        print("ERROR : reading from file \(fileName) : \(error.localizedDescription)")
    }
    return readText
}
Sam Allen
fonte
Em muitas de suas respostas, acho que você não está entendendo meu argumento. (ou você pode não se importar e tudo bem). No entanto, para ficar claro, lançar uma exceção e manipulá-la de alguma forma quando você estiver procurando por um arquivo que não existe (ou tem outro problema, como uma permissão) é muito melhor do que retornar uma string como "ERRO: Arquivo [nome do arquivo] não existe "como a sequência que você deveria realmente ler do arquivo. Depois é só imprimir isso. Se alguma coisa você deve imprimir os detalhes da exceção, não a seqüência de leitura que falhou, que agora possui um erro. O programa provavelmente não deve apenas continuar.
Sam Allen
2

Para o meu arquivo txt funciona desta maneira:

let myFileURL = NSBundle.mainBundle().URLForResource("listacomuni", withExtension: "txt")!
let myText = try! String(contentsOfURL: myFileURL, encoding: NSISOLatin1StringEncoding)
print(String(myText))
Alessandro Mattiuzzi
fonte
2

Para evitar confusão e aumentar a facilidade, criei duas funções para ler e gravar seqüências de caracteres em arquivos no diretório de documentos. Aqui estão as funções:

func writeToDocumentsFile(fileName:String,value:String) {
    let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as! NSString
    let path = documentsPath.stringByAppendingPathComponent(fileName)
    var error:NSError?
    value.writeToFile(path, atomically: true, encoding: NSUTF8StringEncoding, error: &error)
}

func readFromDocumentsFile(fileName:String) -> String {
    let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as! NSString
    let path = documentsPath.stringByAppendingPathComponent(fileName)
    var checkValidation = NSFileManager.defaultManager()
    var error:NSError?
    var file:String

    if checkValidation.fileExistsAtPath(path) {
        file = NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding, error: nil) as! String
    } else {
        file = "*ERROR* \(fileName) does not exist."
    }

    return file
}

Aqui está um exemplo de seu uso:

writeToDocumentsFile("MyText.txt","Hello world!")

let value = readFromDocumentsFile("MyText.txt")
println(value)  //Would output 'Hello world!'

let otherValue = readFromDocumentsFile("SomeText.txt")
println(otherValue)  //Would output '*ERROR* SomeText.txt does not exist.'

Espero que isto ajude!

Versão Xcode: 6.3.2

gooroo7
fonte
2

Código swift3 mais recente
Você pode ler dados do arquivo de texto, basta usar o código abaixo Este é o meu arquivo de texto

     {
"NumberOfSlices": "8",
"NrScenes": "5",
"Scenes": [{
           "dataType": "label1",
           "image":"http://is3.mzstatic.com/image/thumb/Purple19/v4/6e/81/31/6e8131cf-2092-3cd3-534c-28e129897ca9/mzl.syvaewyp.png/53x53bb-85.png",

           "value": "Hello",
           "color": "(UIColor.red)"
           }, {
           "dataType": "label2",
           "image":"http://is1.mzstatic.com/image/thumb/Purple71/v4/6c/4c/c1/6c4cc1bc-8f94-7b13-f3aa-84c41443caf3/mzl.hcqvmrix.png/53x53bb-85.png",
           "value": "Hi There",
           "color": "(UIColor.blue)"
           }, {
           "dataType": "label3",
           "image":"http://is1.mzstatic.com/image/thumb/Purple71/v4/6c/4c/c1/6c4cc1bc-8f94-7b13-f3aa-84c41443caf3/mzl.hcqvmrix.png/53x53bb-85.png",

           "value": "hi how r u ",
           "color": "(UIColor.green)"
           }, {
           "dataType": "label4",
           "image":"http://is1.mzstatic.com/image/thumb/Purple71/v4/6c/4c/c1/6c4cc1bc-8f94-7b13-f3aa-84c41443caf3/mzl.hcqvmrix.png/53x53bb-85.png",
           "value": "what are u doing  ",
           "color": "(UIColor.purple)"
           }, {
           "dataType": "label5",
          "image":"http://is1.mzstatic.com/image/thumb/Purple71/v4/6c/4c/c1/6c4cc1bc-8f94-7b13-f3aa-84c41443caf3/mzl.hcqvmrix.png/53x53bb-85.png",
           "value": "how many times ",
           "color": "(UIColor.white)"
           }, {
           "dataType": "label6",
           "image":"http://is1.mzstatic.com/image/thumb/Purple71/v4/5a/f3/06/5af306b0-7cac-1808-f440-bab7a0d18ec0/mzl.towjvmpm.png/53x53bb-85.png",
           "value": "hi how r u ",
           "color": "(UIColor.blue)"
           }, {
           "dataType": "label7",
           "image":"http://is5.mzstatic.com/image/thumb/Purple71/v4/a8/dc/eb/a8dceb29-6daf-ca0f-d037-df9f34cdc476/mzl.ukhhsxik.png/53x53bb-85.png",
           "value": "hi how r u ",
           "color": "(UIColor.gry)"
           }, {
           "dataType": "label8",
           "image":"http://is2.mzstatic.com/image/thumb/Purple71/v4/15/23/e0/1523e03c-fff2-291e-80a7-73f35d45c7e5/mzl.zejcvahm.png/53x53bb-85.png",
           "value": "hi how r u ",
           "color": "(UIColor.brown)"
           }]

}

Você pode usar esse código para obter dados do arquivo json de texto no swift3

     let filePath = Bundle.main.path(forResource: "nameoftheyourjsonTextfile", ofType: "json")


    let contentData = FileManager.default.contents(atPath: filePath!)
    let content = NSString(data: contentData!, encoding: String.Encoding.utf8.rawValue) as? String

    print(content)
    let json = try! JSONSerialization.jsonObject(with: contentData!) as! NSDictionary
    print(json)
    let app = json.object(forKey: "Scenes") as! NSArray!
    let _ : NSDictionary
    for dict in app! {
        let colorNam = (dict as AnyObject).object(forKey: "color") as! String
        print("colors are \(colorNam)")

       // let colour = UIColor(hexString: colorNam) {
       // colorsArray.append(colour.cgColor)
       // colorsArray.append(colorNam  as! UIColor)

        let value = (dict as AnyObject).object(forKey: "value") as! String
        print("the values are \(value)")
        valuesArray.append(value)

        let images = (dict as AnyObject).object(forKey: "image") as! String
        let url = URL(string: images as String)
        let data = try? Data(contentsOf: url!)
        print(data)
        let image1 = UIImage(data: data!)! as UIImage
        imagesArray.append(image1)
         print(image1)
            }
Gangireddy Rami Reddy
fonte
2

Isso funciona com o Swift 3.1.1 no Linux:

import Foundation

let s = try! String(contentsOfFile: "yo", encoding: .utf8)
Adam Dingle
fonte
1

escrever em ViewDidLoad

var error: NSError?
var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
var documentsDirectory = paths.first as String
var dataPath = documentsDirectory.stringByAppendingPathComponent("MyFolder")

if !NSFileManager.defaultManager().fileExistsAtPath(dataPath) {
    NSFileManager.defaultManager().createDirectoryAtPath(dataPath, withIntermediateDirectories: false, attributes: nil, error: &error)
} else {
    println("not creted or exist")
}

func listDocumentDirectoryfiles() -> [String] {
    if let documentDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as? String {
        let myFilePath = documentDirectory.stringByAppendingPathComponent("MyFolder")
        return NSFileManager.defaultManager().contentsOfDirectoryAtPath(myFilePath, error: nil) as [String]
    }
    return []
}
NRV
fonte
1

As soluções anteriores respondem à pergunta, mas no meu caso, excluir o conteúdo antigo do arquivo enquanto escrevia era um problema.

Então, criei um pedaço de código para gravar em um arquivo no diretório de documentos sem excluir o conteúdo anterior. Você provavelmente precisa de uma melhor manipulação de erros, mas acredito que seja um bom ponto de partida. Swift 4. Uso:

    let filename = "test.txt"
    createOrOverwriteEmptyFileInDocuments(filename: filename)
    if let handle = getHandleForFileInDocuments(filename: filename) {
        writeString(string: "aaa", fileHandle: handle)
        writeString(string: "bbb", fileHandle: handle)
        writeString(string: "\n", fileHandle: handle)
        writeString(string: "ccc", fileHandle: handle)
    }

Métodos auxiliares:

func createOrOverwriteEmptyFileInDocuments(filename: String){
    guard let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
        debugPrint("ERROR IN createOrOverwriteEmptyFileInDocuments")
        return
    }
    let fileURL = dir.appendingPathComponent(filename)
    do {
        try "".write(to: fileURL, atomically: true, encoding: .utf8)
    }
    catch {
        debugPrint("ERROR WRITING STRING: " + error.localizedDescription)
    }
    debugPrint("FILE CREATED: " + fileURL.absoluteString)
}

private func writeString(string: String, fileHandle: FileHandle){
    let data = string.data(using: String.Encoding.utf8)
    guard let dataU = data else {
        debugPrint("ERROR WRITING STRING: " + string)
        return
    }
    fileHandle.seekToEndOfFile()
    fileHandle.write(dataU)
}

private func getHandleForFileInDocuments(filename: String)->FileHandle?{
    guard let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
        debugPrint("ERROR OPENING FILE")
        return nil
    }
    let fileURL = dir.appendingPathComponent(filename)
    do {
        let fileHandle: FileHandle? = try FileHandle(forWritingTo: fileURL)
        return fileHandle
    }
    catch {
        debugPrint("ERROR OPENING FILE: " + error.localizedDescription)
        return nil
    }
}
Szuwar_Jr
fonte
1

Swift 3.x - 5.x

O melhor exemplo é criar um local Logfilecom uma extensão .txt que possa ser visível e mostrada na "Files App"data e hora atuais como um nome de arquivo

basta adicionar este código em info.plist ative esses dois recursos

  UIFileSharingEnabled
  LSSupportsOpeningDocumentsInPlace

e esta função abaixo

var logfileName : String = ""
func getTodayString() -> String{

    let date = Date()
    let calender = Calendar.current
    let components = calender.dateComponents([.year,.month,.day,.hour,.minute,.second], from: date)

    let year = components.year
    let month = components.month
    let day = components.day
    let hour = components.hour
    let minute = components.minute
    let second = components.second

    let today_string = String(year!) + "-" + String(month!) + "-" + String(day!) + "-" + String(hour!)  + "" + String(minute!) + "" +  String(second!)+".txt"

    return today_string

}

func LogCreator(){
    logfileName = getTodayString()

    print("LogCreator: Logfile Generated Named: \(logfileName)")

    let file = logfileName //this is the file. we will write to and read from it

    let text = "some text" //just a text

    if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {

        let fileURL = dir.appendingPathComponent(file)
        let documentPath = NSSearchPathForDirectoriesInDomains(.documentDirectory,.userDomainMask, true)[0]
        print("LogCreator: The Logs are Stored at location \(documentPath)")


        //writing
        do {
            try text.write(to: fileURL, atomically: false, encoding: .utf8)
        }
        catch {/* error handling here */}

        //reading
        do {
            let text2 = try String(contentsOf: fileURL, encoding: .utf8)
            print("LogCreator: The Detail log are :-\(text2)")
        }
        catch {/* error handling here */}
    }
}


  [1]: https://i.stack.imgur.com/4eg12.png
Vishal Shelake
fonte
Eu tentei isso, mas deve ter perdido alguma coisa. Ele salva meu documento e o coloca em arquivo: /// var / mobile / Containers / Data / Application / E4BF1065-3B48-4E53-AC1D-0DC893CCB498 / Documents / mas não consigo encontrá-lo em arquivos.
user3069232 29/04
1
Eu perdi ESTA tecla ... <key> CFBundleDisplayName </key> <string> $ {PRODUCT_NAME} </string> trabalhou no iOS 13, Swift 5
user3069232 29/04
0
 func writeToDocumentsFile(fileName:String,value:String) {
    let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
    let path = documentsPath.appendingPathComponent(fileName)
    do{
    try value.write(toFile: path, atomically: true, encoding: String.Encoding.utf8)
}catch{
    }
    }

func readFromDocumentsFile(fileName:String) -> String {
    let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
    let path = documentsPath.appendingPathComponent(fileName)
    let checkValidation = FileManager.default
    var file:String

    if checkValidation.fileExists(atPath: path) {
        do{
       try file = NSString(contentsOfFile: path, encoding: String.Encoding.utf8.rawValue) as String
        }catch{
            file = ""
        }
        } else {
        file = ""
    }

    return file
}
maroc
fonte
0

Xcode 8.3.2 Swift 3.x . Usando NSKeyedArchiver e NSKeyedUnarchiver

Lendo arquivo de documentos

let documentsDirectoryPathString = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let documentsDirectoryPath = NSURL(string: documentsDirectoryPathString)!
let jsonFilePath = documentsDirectoryPath.appendingPathComponent("Filename.json")

let fileManager = FileManager.default
var isDirectory: ObjCBool = false

if fileManager.fileExists(atPath: (jsonFilePath?.absoluteString)!, isDirectory: &isDirectory) {

let finalDataDict = NSKeyedUnarchiver.unarchiveObject(withFile: (jsonFilePath?.absoluteString)!) as! [String: Any]
}
else{
     print("File does not exists")
}

Gravar arquivo em documentos

NSKeyedArchiver.archiveRootObject(finalDataDict, toFile:(jsonFilePath?.absoluteString)!)
Prashant Gaikwad
fonte