Ajouter du texte ou des données au fichier texte de Swift
j'ai déjà lu lire et écrire des données à partir du fichier texte
je dois ajouter les données (une chaîne) à la fin de mon fichier texte.
Une façon évidente de le faire est de lire le fichier à partir du disque et d'ajouter la chaîne à la fin de celui-ci et de l'écrire en retour, mais ce n'est pas efficace, surtout si vous avez affaire à de grands fichiers et le faire souvent.
donc la question est " comment ajouter une chaîne jusqu'à la fin d'un fichier texte, sans lire le fichier et écrire tout"?
jusqu'à présent j'ai:
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)")
}
5 réponses
vous devez utiliser NSFileHandle, il peut chercher à la fin du fichier
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)")
}
}
Voici une mise à jour pour la réponse de PointZeroTwo dans Swift 3.0, avec une note rapide - dans le terrain de jeu de test à l'aide d'un simple filepath fonctionne, mais dans mon application actuelle, j'ai dû construire L'URL en utilisant .documentDirectory (ou le répertoire que vous avez choisi d'utiliser pour lire et écrire - assurez-vous qu'il est cohérent dans toute votre application):
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")
}
Merci PointZeroTwo.
Voici une version pour Swift 2, en utilisant des méthodes d'extension sur la chaîne de caractères et 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")
}
mise à Jour: j'ai écrit un billet de blog sur ce que vous pouvez trouver ici !
Keeping things Swifty , voici un exemple d'utilisation d'un protocole FileWriter
avec implémentation par défaut (Swift 4.1 au moment de la rédaction):
- pour utiliser ceci, faites que votre entité (class, struct, enum) se conforme à ce protocole et appelez la fonction write (pour info, il lance!).
- écrit dans le répertoire des documents.
- ajouter le fichier texte si le fichier existe.
- Va créer un nouveau fichier si le fichier texte n'existe pas.
-
Note: Ceci est uniquement pour le texte. Vous pourriez faire quelque chose de similaire à écrire/ajouter
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) } } }
pour rester dans L'esprit PointZero deux. Voici une mise à jour de son code 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)
}
}
}