Añada texto o datos al archivo de texto en Swift

Ya he leído Leer y escribir datos desde archivo de texto

Necesito agregar los datos (una cadena) al final de mi archivo de texto.
Una forma obvia de hacerlo es leer el archivo desde el disco y agregar la cadena al final y volver a escribirlo, pero no es eficiente, especialmente si se trata de archivos grandes y se realizan con frecuencia.

Entonces, la pregunta es “¿Cómo agregar una cadena al final de un archivo de texto, sin leer el archivo y escribir todo de nuevo?”

hasta ahora tengo:

let dir:NSURL = NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.CachesDirectory, inDomains: NSSearchPathDomainMask.UserDomainMask).last as NSURL let fileurl = dir.URLByAppendingPathComponent("log.txt") var err:NSError? // until we find a way to append stuff to files if let current_content_of_file = NSString(contentsOfURL: fileurl, encoding: NSUTF8StringEncoding, error: &err) { "\(current_content_of_file)\n\(NSDate()) -> \(object)".writeToURL(fileurl, atomically: true, encoding: NSUTF8StringEncoding, error: &err) }else { "\(NSDate()) -> \(object)".writeToURL(fileurl, atomically: true, encoding: NSUTF8StringEncoding, error: &err) } if err != nil{ println("CANNOT LOG: \(err)") } 

Debe usar NSFileHandle, puede buscar hasta el final del archivo

 let dir:NSURL = NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.CachesDirectory, inDomains: NSSearchPathDomainMask.UserDomainMask).last as NSURL let fileurl = dir.URLByAppendingPathComponent("log.txt") let string = "\(NSDate())\n" let data = string.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)! if NSFileManager.defaultManager().fileExistsAtPath(fileurl.path!) { var err:NSError? if let fileHandle = NSFileHandle(forWritingToURL: fileurl, error: &err) { fileHandle.seekToEndOfFile() fileHandle.writeData(data) fileHandle.closeFile() } else { println("Can't open fileHandle \(err)") } } else { var err:NSError? if !data.writeToURL(fileurl, options: .DataWritingAtomic, error: &err) { println("Can't write \(err)") } } 

Aquí hay una actualización de la respuesta de PointZeroTwo en Swift 3.0, con una nota rápida: en la prueba de campo usando un simple archivo de ruta, pero en mi aplicación real necesitaba construir la URL usando .documentDirectory (o el directorio que elegiste usar para leer y escribir, asegúrese de que sea consistente en toda su aplicación):

 extension String { func appendLineToURL(fileURL: URL) throws { try (self + "\n").appendToURL(fileURL: fileURL) } func appendToURL(fileURL: URL) throws { let data = self.data(using: String.Encoding.utf8)! try data.append(fileURL: fileURL) } } extension Data { func append(fileURL: URL) throws { if let fileHandle = FileHandle(forWritingAtPath: fileURL.path) { defer { fileHandle.closeFile() } fileHandle.seekToEndOfFile() fileHandle.write(self) } else { try write(to: fileURL, options: .atomic) } } } //test do { let dir: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last! as URL let url = dir.appendingPathComponent("logFile.txt") try "Test \(Date())".appendLineToURL(fileURL: url as URL) let result = try String(contentsOf: url as URL, encoding: String.Encoding.utf8) } catch { print("Could not write to file") } 

Gracias PointZeroTwo.

Aquí hay una versión para Swift 2, que usa métodos de extensión en String y NSData.

 //: Playground - noun: a place where people can play import UIKit extension String { func appendLineToURL(fileURL: NSURL) throws { try self.stringByAppendingString("\n").appendToURL(fileURL) } func appendToURL(fileURL: NSURL) throws { let data = self.dataUsingEncoding(NSUTF8StringEncoding)! try data.appendToURL(fileURL) } } extension NSData { func appendToURL(fileURL: NSURL) throws { if let fileHandle = try? NSFileHandle(forWritingToURL: fileURL) { defer { fileHandle.closeFile() } fileHandle.seekToEndOfFile() fileHandle.writeData(self) } else { try writeToURL(fileURL, options: .DataWritingAtomic) } } } // Test do { let url = NSURL(fileURLWithPath: "test.log") try "Test \(NSDate())".appendLineToURL(url) let result = try String(contentsOfURL: url) } catch { print("Could not write to file") } 

Actualización: ¡escribí una publicación de blog sobre esto, que puedes encontrar aquí !

Manteniendo Swifty , aquí hay un ejemplo usando un protocolo FileWriter con implementación predeterminada (Swift 4.1 en el momento de escribir esto):

  • Para usar esto, haga que su entidad (clase, estructura, enumeración) se ajuste a este protocolo y llame a la función de escritura (¡fyi, arroja!).
  • Escribe en el directorio de documentos.
  • Se agregará al archivo de texto si el archivo existe.
  • Creará un nuevo archivo si el archivo de texto no existe.
  • Nota: esto es solo para texto. Podría hacer algo similar para escribir / anexar Data .

     import Foundation enum FileWriteError: Error { case directoryDoesntExist case convertToDataIssue } protocol FileWriter { var fileName: String { get } func write(_ text: String) throws } extension FileWriter { var fileName: String { return "File.txt" } func write(_ text: String) throws { guard let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { throw FileWriteError.directoryDoesntExist } let encoding = String.Encoding.utf8 guard let data = text.data(using: encoding) else { throw FileWriteError.convertToDataIssue } let fileUrl = dir.appendingPathComponent(fileName) if let fileHandle = FileHandle(forWritingAtPath: fileUrl.path) { fileHandle.seekToEndOfFile() fileHandle.write(data) } else { try text.write(to: fileUrl, atomically: false, encoding: encoding) } } } 

Para mantenerse en el espíritu PointZero Two. Aquí una actualización de su código para Swift 4.1

 extension String { func appendLine(to url: URL) throws { try self.appending("\n").append(to: url) } func append(to url: URL) throws { let data = self.data(using: String.Encoding.utf8) try data?.append(to: url) } } extension Data { func append(to url: URL) throws { if let fileHandle = try? FileHandle(forWritingTo: url) { defer { fileHandle.closeFile() } fileHandle.seekToEndOfFile() fileHandle.write(self) } else { try write(to: url) } } } 
    Intereting Posts