在Swift中读取,写入和删除文件

当今大多数普通应用程序都是通过HTTP进行通信的。 虽然我们可以通过这种方式读取和写入数据,但仍然需要将数据保存到设备本地文件中,这仍然非常普遍。 让我们讨论一下如何完成,然后提出一种更简单的方法。

TL; DR

如果您不希望自己学习如何做,请在GitHub上查看我的File项目(但您确实应该知道它是如何完成的,因此请继续阅读!)。

FileManager和URL

刚开始在iOS中进行文件处理时,它会令人望而生畏。 您必须学习FileManager,在您发现需要传递URL之前,它看起来还不错。 然后,您停下来思考:“等等,URL与保存文件有什么关系? 这令人困惑。”

Apple选择使用URL作为通用语言来传达文件在文件系统中的位置。 一旦您对这个概念有所了解,它确实非常巧妙。 通过字符串处理文件位置可能会很混乱(我有数十行的旧服务器代码用于遍历目录和文件以证明这一点),但是使用URL会将它们包装在一个非常需要的结构中,该结构相对容易理解和理解。如果您以前使用过URL进行联网,则很熟悉。 即使您以前从未使用过URL,我们所需的基础知识也确实很容易。 实际上,可以将其全部简化为包含三个简单步骤的模式:

1.创建目标目录URL
2.使用目录URL创建文件URL
3.将数据保存到文件URL

让我们看一下这是如何完成的。

注意:如果您以前从未使用过FileManager,请知道它使用Singleton模式,并且不直接实例化FileManager,而是使用FileManager.default来调用FileManager的属性和函数。 如果您不熟悉单例模式,那是确保在应用程序的生命周期中仅实例化类的一个实例的一种方法。

目录网址

首先,我们需要一个用于文档目录的URL。 您不必将所有内容都保存到documents目录,但这是最合乎逻辑的开始,并且一旦您知道如何保存在那里,就很容易保存到其他位置。 我们将使用以下代码来获取文档目录的URL:

 让directoryURL = FileManager.default.urls(用于:.documentDirectory,在:.userDomainMask中)[0] 

我们在这里要做的是向FileManager索要用户主目录(或在iOS中为应用程序的主目录)中文档目录的URL列表。 这将返回一个数组,其第一个条目将包含documents目录,这就是为什么我们在语句末尾指定[0]的第一个数组索引的原因。 这将返回文档目录的URL对象。 真的就是这么简单。

档案网址

现在我们有了要保存文件的目录的URL,让我们创建文件本身的URL。 为此,我们使用URL(fileURLWithPath:relativeTo:)fileURLWithPath参数中引用的路径是文件名,不包括任何文件扩展名。 例如,如果我们想要一个名为“ myFile.txt”的文件,则fileURLWithPath将为“ myFile”(我稍后将解决“ .txt”扩展名)。 接下来, relativeTo参数是文件将保存到的目录。 该参数带有一个URL ,您猜到了,我们将简单地传入上面的URL

 让fileURL = URL(fileURLWithPath:“ myFile”,relativeTo:directoryURL) 

好吧,那文件扩展名呢? 要添加该代码,只需在调用末尾添加appendingPathExtension(:) ,如下所示:

  let fileURL = URL(fileURLWithPath:“ myFile”,relativeTo:directoryURL).appendingPathExtension(“ txt”) 

这将为我们提供该应用程序的文档目录文件夹中的myFile.txtURL ,只需两行代码即可。 还不错吧?

保存数据

现在,让我们实际保存一些数据:

  //创建要保存的数据 
let myString =“使用FileManager轻松保存数据!”
警卫让数据= myString.data(使用:.utf8),否则{
打印(“无法将字符串转换为数据”)
返回
}
  //保存数据 
做{
尝试data.write(to:fileURL)
打印(“文件已保存:\(fileURL.absoluteURL)”)
} {
//捕获任何错误
打印(error.localizedDescription)
}

首先,我们创建一个数据对象,其中包含要保存的数据。 在这种情况下,一个简单的字符串。 然后,我们将字符串转换为数据。 接下来,我们使用do/catch块包装数据的写入,以防万一出现错误。 如您所见,数据的实际写入非常简单,可以通过将文件URL作为参数传递给Datawrite(:)函数来完成。 最后,如果发生错误,我们将打印错误。

就是这样。 假设您已经创建了数据,那么只需几行代码就可以完成所有操作。

读取数据

现在我们已经保存了数据,在某些时候我们将要读回它。 事实证明,这就像保存它一样容易,尤其是现在有了文件URL:

 做{ 
//获取保存的数据
让savedData =尝试数据(contentsOf:fileURL)
//将数据转换回字符串
如果让savedString = String(数据:savedData,编码:.utf8){
打印(savedString)
}
} {
//捕获任何错误
打印(“无法读取文件”)
}

删除资料

现在我们已经保存了文件并读取了其内容,让我们看一下如何删除该文件。 再一次,这确实很简单。

 尝试FileManager.default.removeItem(at:fileURL) 

我们只需将先前创建的fileURL对象传递到FileManagerremoveItem(at:)方法中。 此方法不返回任何值,但是如果无法删除该文件,则会引发错误,因此建议您将其包装在do/catch块中。

这如何变得更容易?

如所承诺的,保存,读取和删除数据并不困难。 但是我确实说过,我将向您展示更简单的方法,那是什么呢?

在我的GitHub上,我有一个名为File的开源项目,该项目实质上是FileManager的包装,可用于仅两行代码来保存,读取或删除文件:

 让fileURLComponents = FileURLComponents( 
fileName:“ mySecondFile”,
fileExtension:“ txt”,
directoryName:无,
directoryPath:.documentDirectory)
尝试? File.write(数据,转至:fileURLComponents)

那么,这里发生了什么? 首先,我们创建一个FileURLComponents对象,该对象是File一部分。 从本质上讲,它允许您输入通常用于构建FileManager URL\对象的所有参数,并根据这些File在内部构建URL。 fileName参数是文件的名称, fileExtension参数是文件的扩展名, directoryName是文件应相对于directoryPath保存的directoryPath 。 在这种情况下,我们将nil传递给directoryName因此该文件将像以前一样直接存储在documents目录中。 最后,将数据和URL组件发送到File.write函数,该函数负责创建URL和保存数据。 在真实的应用程序中,您将需要使用正确的错误处理将File.write包装在do语句中。

从保存的文件中读取数据同样容易。 假设您已经有了FileURLComponents ,则只需使用File.read函数:

 让savedData =尝试?  File.read(来自:fileURLComponents) 

最后,删除文件可能正是您此时所期望的:

 尝试File.delete(fileURLComponents) 

这几乎就是全部。

从这往哪儿走

如果您喜欢冒险,请继续阅读有关FileManager和URL的更多信息。 学习Apple提供的API是使自己成为更好的iOS开发人员的最佳方法之一。 即使您使用File之类的包装器,我也强烈建议您学习FileManager,因为FileManager可以完成很多工作,例如目录遍历和我计划在以后的文章中介绍的其他操作。

对于只需要快速启动和运行的应用程序,可以从Github下载File。 在本文发布时,File只能读取,写入和删除文件,但是更多功能即将推出。

如果您有以下任何问题或建议,请告诉我。 如果您在文章中发现错误,请发表评论。

弗雷迪·雅各布 Fredy Jacob)