Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/codeigniter/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Swift中向文本文件追加文本或数据_Swift_Append_Text Files - Fatal编程技术网

在Swift中向文本文件追加文本或数据

在Swift中向文本文件追加文本或数据,swift,append,text-files,Swift,Append,Text Files,我已经读过了 我需要将数据(字符串)附加到文本文件的末尾。 一种显而易见的方法是从磁盘读取文件,并将字符串附加到文件末尾,然后将其写回,但这并不高效,特别是当您处理大型文件时,并且经常在磁盘中执行此操作 所以问题是“如何将字符串附加到文本文件的末尾,而不读取文件并将整个内容写回” 到目前为止,我已经: let dir:NSURL = NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.CachesDi

我已经读过了

我需要将数据(字符串)附加到文本文件的末尾。
一种显而易见的方法是从磁盘读取文件,并将字符串附加到文件末尾,然后将其写回,但这并不高效,特别是当您处理大型文件时,并且经常在磁盘中执行此操作

所以问题是“如何将字符串附加到文本文件的末尾,而不读取文件并将整个内容写回”

到目前为止,我已经:

    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)")
    }

您应该使用NSFileHandle,它可以


下面是Swift 2的一个版本,它对字符串和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")
}

下面是对Swift 3.0中PointZeroTwo答案的更新,其中有一个提示-在操场上使用简单的文件路径进行测试是可行的,但在我的实际应用中,我需要使用.documentDirectory(或您选择用于读写的任何目录-确保它在整个应用程序中保持一致)来构建URL:


谢谢零点二。

更新:我写了一篇关于这一点的博客文章,你可以找到

为了保持快速,下面是一个使用默认实现的
FileWriter
协议的示例(撰写本文时为Swift 4.1):

  • 要使用它,请让您的实体(类、结构、枚举)符合此协议,并调用write函数(仅供参考,它会抛出!)
  • 写入文档目录
  • 如果文件存在,将附加到文本文件
  • 如果文本文件不存在,将创建一个新文件
  • 注意:这仅适用于文本。您可以执行类似于写入/追加
    数据的操作

    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)
            }
        }
    }
    

    • 以保持@PointZero-Two的精神。 这里是他的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)
              }
          }
      }
      

      下面是一种以更高效的方式更新文件的方法

      let monkeyLine = "\nAdding a A variation over some of the posted answers, with following characteristics:

      • based on Swift 5
      • accessible as a static function
      • appends new entries to the end of the file, if it exists
      • creates the file, if it doesn't exist
      • no cast to NS objects (more Swiftly)
      • fails silently if the text cannot be encoded or the path does not exist

        class Logger {
        
            static var logFile: URL? {
                guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return nil }
                let formatter = DateFormatter()
                formatter.dateFormat = "dd-MM-yyyy"
                let dateString = formatter.string(from: Date())
                let fileName = "\(dateString).log"
                return documentsDirectory.appendingPathComponent(fileName)
            }
        
            static func log(_ message: String) {
                guard let logFile = logFile else {
                    return
                }
        
                let formatter = DateFormatter()
                formatter.dateFormat = "HH:mm:ss"
                let timestamp = formatter.string(from: Date())
                guard let data = (timestamp + ": " + message + "\n").data(using: String.Encoding.utf8) else { return }
        
                if FileManager.default.fileExists(atPath: logFile.path) {
                    if let fileHandle = try? FileHandle(forWritingTo: logFile) {
                        fileHandle.seekToEndOfFile()
                        fileHandle.write(data)
                        fileHandle.closeFile()
                    }
                } else {
                    try? data.write(to: logFile, options: .atomicWrite)
                }
            }
        }
        

        let monkeyLine=“\n在一些发布的答案上添加一个变体,具有以下特征:

        • 基于Swift 5
        • 可作为静态函数访问
        • 将新条目追加到文件末尾(如果存在)
        • 如果文件不存在,则创建该文件
        • 不强制转换到NS对象(更快)
        • 如果无法对文本进行编码或路径不存在,则以静默方式失败


        如果您只需单击Xcode中带有白点的红色小圆圈,您会惊讶地发现将其转换为swift 3是多么容易。我正在尝试使用它,但我不知道如何做到这一点……”让您的实体(类、结构、枚举)符合此协议并调用写函数(仅供参考,它抛出!)“。我实际上如何调用它来保存VC中文本视图中的文本?这将两个概念联系在一起:符合协议&使用协议扩展来提供默认功能。首先,您的实体应该符合协议(例如,类MyClass:FileWriter)。现在,由于在
        FileWriter
        协议上有一个协议要求的默认实现扩展,因此您的实体MyClass在本例中免费获得写入功能!因此,您可以在MyClass的实例上调用该函数。(例如,让myClassInstance=MyClass();试试!myClassInstance.write(“hello”))。此外,如果您想获得更详细的示例说明,请查看我的博客帖子,我在上面的回答中添加了一个链接:)。@John你是什么意思?您好@atineoSE在FileManager被否决后,您有什么关于如何使用的信息吗?看起来像var writeabilityHandler:((FileHandle)->Void)?是异步版本,工作非常出色。谢谢
        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)
                }
            }
        }
        
        let monkeyLine = "\nAdding a A variation over some of the posted answers, with following characteristics:

        • based on Swift 5
        • accessible as a static function
        • appends new entries to the end of the file, if it exists
        • creates the file, if it doesn't exist
        • no cast to NS objects (more Swiftly)
        • fails silently if the text cannot be encoded or the path does not exist

          class Logger {
          
              static var logFile: URL? {
                  guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return nil }
                  let formatter = DateFormatter()
                  formatter.dateFormat = "dd-MM-yyyy"
                  let dateString = formatter.string(from: Date())
                  let fileName = "\(dateString).log"
                  return documentsDirectory.appendingPathComponent(fileName)
              }
          
              static func log(_ message: String) {
                  guard let logFile = logFile else {
                      return
                  }
          
                  let formatter = DateFormatter()
                  formatter.dateFormat = "HH:mm:ss"
                  let timestamp = formatter.string(from: Date())
                  guard let data = (timestamp + ": " + message + "\n").data(using: String.Encoding.utf8) else { return }
          
                  if FileManager.default.fileExists(atPath: logFile.path) {
                      if let fileHandle = try? FileHandle(forWritingTo: logFile) {
                          fileHandle.seekToEndOfFile()
                          fileHandle.write(data)
                          fileHandle.closeFile()
                      }
                  } else {
                      try? data.write(to: logFile, options: .atomicWrite)
                  }
              }
          }