【问题标题】:Read and write a String from text file从文本文件中读取和写入字符串
【发布时间】:2014-07-28 16:02:00
【问题描述】:

我需要在文本文件中读取和写入数据,但我无法弄清楚如何。

我在 Swift 的 iBook 中找到了这个示例代码,但我仍然不知道如何写入或读取数据。

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."

【问题讨论】:

    标签: swift string file-io


    【解决方案1】:

    对于读取和写入,您应该使用可写入的位置,例如文档目录。下面的代码展示了如何读取和写入一个简单的字符串。您可以在操场上进行测试。

    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 */}
    }
    

    斯威夫特 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)
    }
    

    【讨论】:

    • let text2 = String.stringWithContentsOfFile(path) // XCode 6.0
    • 使用此解决方案有效,但如果我打开文件,其中没有文本。我错过了什么吗?
    • @Adam 这个文件是什么在 let path = dir.stringByAppendingPathComponent(file);?
    • 这应该被删除,代码不适用于新版本的 Swift。
    • @billy_b29 此行之后的代码://reading 正是这样做的。
    【解决方案2】:

    假设您已将文本文件 data.txt 移动到 Xcode 项目中(使用拖放操作并选中“如有必要复制文件”),您可以像在 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
    

    更新:
    要从 Bundle (iOS) 读取文件,您可以使用:

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

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

    对于 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)
    

    【讨论】:

    • 对于 iOS 项目,“stringWithContentsOfFile”不可用(iOS 7 已弃用)
    • 与 iOS 项目无关,它已被弃用,不再适用于 Xcode 6.1(包括 Mac OS X)
    • 你可以使用 String(contentsOfFile: ...)
    • 类似的解决方案使用捆绑 iOS 10 Swift 3 here
    【解决方案3】:

    Xcode 8.x • Swift 3.x 或更高版本

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

    【讨论】:

    • “没有这样的文件”最常见的错误是什么。因为我将我的 .txt 文件添加到项目导航器,然后我尝试打开它们,所以我收到了这条消息。 (在桌面上创建它们并将它们拖到项目导航器)
    【解决方案4】:

    新的更简单的推荐方法: Apple 建议使用 URL 进行文件处理,而这里的其他解决方案似乎已被弃用(请参阅下面的 cmets)。 以下是使用 URL 读写的新的简单方法(不要忘记处理可能的 URL 错误):

    Swift 5+、4 和 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)")
    }
    

    【讨论】:

    • 你能提供一个苹果推荐这种方式的参考吗?或者您能否详细说明为什么这是推荐的方式?
    • @Andrej "URL 对象是引用本地文件的首选方式。大多数从文件读取数据或向文件写入数据的对象都有接受 NSURL 对象而不是路径名作为文件引用的方法。” developer.apple.com/library/ios/documentation/Cocoa/Reference/…
    • 您不必将错误转换为 NSError,甚至不必使用“catch let error”。您只需执行 catch 即可免费获得错误变量。
    • @cuomo456 你的权利我删除它,它是以前 Swift 测试版的遗留物。
    • @Alshcompiler create: true 通知 FileManager 如果目录不存在则创建目录,而不是失败
    【解决方案5】:

    Xcode 8、Swift 3 从 app bundle 中读取文件的方式:

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

    这是一个方便的复制和粘贴扩展

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

    例如

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

    你几乎总是想要一个行数组:

    let r:[String] = "yourFile.txt"
         .contentsOrBlank()
         .characters
         .split(separator: "\n", omittingEmptySubsequences:ignore)
         .map(String.init)
    

    【讨论】:

    • 我粘贴了一个方便的扩展@crashalot - 随意删除,干杯
    • @Alshcompiler 不!您不能将文件写入包中。
    • 我说的是从文件中读取,如果文件在项目文件中,这是唯一对我有用的答案
    【解决方案6】:

    我只想向您展示第一部分,即阅读。以下是您可以轻松阅读的方式:

    斯威夫特 3:

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

    斯威夫特 2:

    let s = try! String(contentsOfFile: NSBundle.mainBundle().pathForResource("myFile", ofType: "txt")!)
    

    【讨论】:

      【解决方案7】:

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

      【讨论】:

        【解决方案8】:

        您可能会发现这个工具不仅可以在 Swift 中读取文件,还可以解析您的输入:https://github.com/shoumikhin/StreamScanner

        只需像这样指定文件路径和数据分隔符:

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

        希望,这会有所帮助。

        【讨论】:

          【解决方案9】:

          上面亚当当前接受的答案对我来说有一些错误,但这是我如何修改他的答案并使它为我工作的方法。

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

          【讨论】:

            【解决方案10】:

            为了避免混淆和增加易用性,我创建了两个函数,用于读取和写入文档目录中的文件的字符串。以下是函数:

            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
            }
            

            以下是它们的使用示例:

            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.'
            

            希望这会有所帮助!

            Xcode 版本:6.3.2

            【讨论】:

              【解决方案11】:

              这适用于 Linux 上的 Swift 3.1.1:

              import Foundation
              
              let s = try! String(contentsOfFile: "yo", encoding: .utf8)
              

              【讨论】:

                【解决方案12】:

                我不得不像这样重新编码:

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

                【讨论】:

                  【解决方案13】:

                  在函数示例中,(read|write)DocumentsFromFile(...) 具有一些函数包装器似乎很有意义,因为 OSx 和 iOS 中的所有内容似乎都需要实例化三到四个主要类和一组配置的属性、链接、实例化和设置,只是为了在 182 个国家/地区将“Hi”写入文件。

                  但是,这些示例还不够完整,无法在实际程序中使用。 write 函数不会报告创建或写入文件的任何错误。在读取时,我认为返回文件不存在作为应该包含已读取数据的字符串的错误不是一个好主意。您会想通过某种通知机制(例如异常)知道它失败以及失败的原因。然后,您可以编写一些代码来输出问题所在并允许用户更正它,或者“正确地”在该点中断程序。

                  您不想只返回一个包含“错误文件不存在”的字符串。然后,您必须每次从调用函数中查找字符串中的错误并在那里处理它。您也可能无法真正判断错误字符串是否实际上是从实际文件中读取的,或者它是否是从您的代码中产生的。

                  您甚至不能在 swift 2.2 和 Xcode 7.3 中这样调用 read,因为 NSString(contentsOfFile...) 会引发异常。如果您没有任何代码来捕获它并对其执行某些操作,例如将其打印到 stdout,或者更好的是错误弹出窗口或 stderr,则这是一个编译时错误。我听说 Apple 正在远离 try catch 和异常,但这将是一个漫长的过程,没有它就不可能编写代码。我不知道 &error 参数来自哪里,可能是旧版本,但是 NSString.writeTo[File|URL] 目前没有 NSError 参数。它们在 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
                  

                  此外,不存在的文件只是您的程序在读取文件时可能遇到的许多潜在问题之一,例如权限问题、文件大小或您甚至不想尝试编码的许多其他问题每个人都有一个处理程序。最好假设一切都是正确的,然后捕获并打印或处理异常,如果出现问题,此外,在这一点上,您实际上别无选择。

                  这是我的重写:

                  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
                  }
                  

                  【讨论】:

                  • 在您的许多回复中,我认为您没有理解我的观点。 (或者你可能不在乎,没关系)。但是,需要明确的是,在查找不存在的文件(或存在其他问题,例如权限)时,抛出异常并以某种方式处理它比返回诸如“错误:文件 [文件名]”之类的字符串要好得多不存在”作为您应该从文件中实际读取的字符串。然后就打印那个。如果有任何内容,您应该打印异常详细信息,而不是现在有错误的无法读取的字符串。程序可能不应该继续。
                  【解决方案14】:

                  因为我的 txt 文件是这样工作的:

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

                  【讨论】:

                    【解决方案15】:

                    最新的 swift3 代码
                    您可以从文本文件中读取数据,只需使用以下代码 这是我的文本文件

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

                    }

                    您可以使用此代码从 swift3 中的文本 json 文件中获取数据

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

                    【讨论】:

                      【解决方案16】:

                      推荐异步读写文件!在纯 Swift 中很容易做到,
                      这是协议:

                      protocol FileRepository {
                          func read(from path: String) throws -> String
                          func readAsync(from path: String, completion: @escaping (Result<String, Error>) -> Void)
                          func write(_ string: String, to path: String) throws
                          func writeAsync(_ string: String, to path: String, completion: @escaping (Result<Void, Error>) -> Void)
                      }
                      

                      如您所见,它允许您同步或异步读取和写入文件。

                      这是我在 Swift 5 中的实现:

                      class DefaultFileRepository {
                          
                          // MARK: Properties
                          
                          let queue: DispatchQueue = .global()
                          let fileManager: FileManager = .default
                          lazy var baseURL: URL = {
                              try! fileManager
                                  .url(for: .libraryDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
                                  .appendingPathComponent("MyFiles")
                          }()
                          
                          
                          // MARK: Private functions
                          
                          private func doRead(from path: String) throws -> String {
                              let url = baseURL.appendingPathComponent(path)
                              
                              var isDir: ObjCBool = false
                              guard fileManager.fileExists(atPath: url.path, isDirectory: &isDir) && !isDir.boolValue else {
                                  throw ReadWriteError.doesNotExist
                              }
                              
                              let string: String
                              do {
                                  string = try String(contentsOf: url)
                              } catch {
                                  throw ReadWriteError.readFailed(error)
                              }
                              
                              return string
                          }
                          
                          private func doWrite(_ string: String, to path: String) throws {
                              let url = baseURL.appendingPathComponent(path)
                              let folderURL = url.deletingLastPathComponent()
                              
                              var isFolderDir: ObjCBool = false
                              if fileManager.fileExists(atPath: folderURL.path, isDirectory: &isFolderDir) {
                                  if !isFolderDir.boolValue {
                                      throw ReadWriteError.canNotCreateFolder
                                  }
                              } else {
                                  do {
                                      try fileManager.createDirectory(at: folderURL, withIntermediateDirectories: true)
                                  } catch {
                                      throw ReadWriteError.canNotCreateFolder
                                  }
                              }
                              
                              var isDir: ObjCBool = false
                              guard !fileManager.fileExists(atPath: url.path, isDirectory: &isDir) || !isDir.boolValue else {
                                  throw ReadWriteError.canNotCreateFile
                              }
                              
                              guard let data = string.data(using: .utf8) else {
                                  throw ReadWriteError.encodingFailed
                              }
                              
                              do {
                                  try data.write(to: url)
                              } catch {
                                  throw ReadWriteError.writeFailed(error)
                              }
                          }
                          
                      }
                      
                      
                      extension DefaultFileRepository: FileRepository {
                          func read(from path: String) throws -> String {
                              try queue.sync { try self.doRead(from: path) }
                          }
                          
                          func readAsync(from path: String, completion: @escaping (Result<String, Error>) -> Void) {
                              queue.async {
                                  do {
                                      let result = try self.doRead(from: path)
                                      completion(.success(result))
                                  } catch {
                                      completion(.failure(error))
                                  }
                              }
                          }
                          
                          func write(_ string: String, to path: String) throws {
                              try queue.sync { try self.doWrite(string, to: path) }
                          }
                          
                          func writeAsync(_ string: String, to path: String, completion: @escaping (Result<Void, Error>) -> Void) {
                              queue.async {
                                  do {
                                      try self.doWrite(string, to: path)
                                      completion(.success(Void()))
                                  } catch {
                                      completion(.failure(error))
                                  }
                              }
                          }
                          
                      }
                      
                      
                      enum ReadWriteError: LocalizedError {
                          
                          // MARK: Cases
                          
                          case doesNotExist
                          case readFailed(Error)
                          case canNotCreateFolder
                          case canNotCreateFile
                          case encodingFailed
                          case writeFailed(Error)
                      }
                      
                      

                      【讨论】:

                      • 这可以用来从 AppBundle 读取文件吗?例如位于appBundle/MyTextFiles/changes.txt 的文件?
                      【解决方案17】:

                      在 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 []
                      }
                      

                      【讨论】:

                        【解决方案18】:
                         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
                        }
                        

                        【讨论】:

                          【解决方案19】:

                          早期的解决方案回答了问题,但在我的情况下,在写入时删除文件的旧内容是一个问题。

                          所以,我创建了一段代码,用于写入文档目录中的文件,而不删除以前的内容。您可能需要更好的错误处理,但我相信这是一个很好的起点。斯威夫特 4。 用法:

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

                          辅助方法:

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

                          【讨论】:

                            【解决方案20】:

                            Swift 3.x - 5.x

                            最好的例子是创建一个本地的Logfile,扩展名为.txt 可以在"Files App" 中以当前日期和时间作为文件名可见和显示

                            只需在 info.plist 中添加此代码即可启用这两个功能

                              UIFileSharingEnabled
                              LSSupportsOpeningDocumentsInPlace
                            

                            下面这个函数

                            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
                            

                            【讨论】:

                            • 我试过这个,但一定漏掉了什么。它保存我的文档并将其放入 file:///var/mobile/Containers/Data/Application/E4BF1065-3B48-4E53-AC1D-0DC893CCB498/Documents/ 但我无法在文件中找到它。
                            • 我错过了这个键... CFBundleDisplayName${PRODUCT_NAME} 在 iOS 13、Swift 5 中工作
                            【解决方案21】:

                            Xcode 8.3.2 Swift 3.x。使用 NSKeyedArchiver 和 NSKeyedUnarchiver

                            从文档中读取文件

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

                            将文件写入文档

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

                            【讨论】:

                              猜你喜欢
                              • 1970-01-01
                              • 2012-01-17
                              • 2011-05-12
                              • 1970-01-01
                              • 1970-01-01
                              • 2012-12-31
                              • 1970-01-01
                              • 1970-01-01
                              相关资源
                              最近更新 更多