企业网站建设的价格,看网红直播做爰的网站,ssh网站开发的书籍,河北石家庄房价转自#xff1a;http://www.apple.com.cn/developer/iphone/library/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/FilesandNetworking/FilesandNetworking.html 文件和数据管理 iPhone OS系统上的文件和用户的媒体数据及个人文件共享闪存上的空间。出于安全的目…转自http://www.apple.com.cn/developer/iphone/library/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/FilesandNetworking/FilesandNetworking.html 文件和数据管理 iPhone OS系统上的文件和用户的媒体数据及个人文件共享闪存上的空间。出于安全的目的您的应用程序被放在其自己的目录下并且只能对该目录进行读写。本章的下面部分将描述应用程序本地文件系统的结构及几个读写文件的技术。 常用目录 出于安全的目的应用程序只能将自己的数据和偏好设置写入到几个特定的位置上。当应用程序被安装到设备上时系统会为其创建一个家目录。表6-1列出了应用程序家目录下的一些重要子目录您的程序可能需要对其进行访问。表中还描述了每个目录的设计目的和访问限制以及iTunes是否对该目录下的内容进行备份。有关备份和恢复过程的更多信息请参见“备份和恢复” 部分有关应用程序家目录本身的信息则请参见 “应用程序沙箱”部分。 表 6-1 iPhone应用程序的目录 目录 描述 Application_Home/AppName.app 这是程序包目录包含应用程序的本身。由于应用程序必须经过签名所以您在运行时不能对这个目录中的内容进行修改否则可能会使应用程序无法启动。 在iPhone OS 2.1及更高版本的系统iTunes不对这个目录的内容进行备份。但是iTunes会对在App Store上购买的应用程序进行一次初始的同步。 Application_Home/Documents/ 您应该将所有的应用程序数据文件写入到这个目录下。这个目录用于存储用户数据或其它应该定期备份的信息。有关如何取得这个目录路径的信息请参见“获取应用程序目录的路径”部分。 iTunes会备份这个目录的内容。 Application_Home/Library/Preferences 这个目录包含应用程序的偏好设置文件。您不应该直接创建偏好设置文件而是应该使用NSUserDefaults类或CFPreferences API来取得和设置应用程序的偏好详情请参见“添加Settings程序包”部分。 iTunes会备份这个目录的内容。 Application_Home/Library/Caches 这个目录用于存放应用程序专用的支持文件保存应用程序再次启动过程中需要的信息。您的应用程序通常需要负责添加和删除这些文件但在对设备进行完全恢复的过程中iTunes会删除这些文件因此您应该能够在必要时重新创建。您可以使用“获取应用程序目录的路径” 部分描述的接口来获取该目录的路径并对其进行访问。 在iPhone OS 2.2及更高版本iTunes不对这个目录的内容进行备份。 Application_Home/tmp/ 这个目录用于存放临时文件保存应用程序再次启动过程中不需要的信息。当您的应用程序不再需要这些临时文件时应该将其从这个目录中删除系统也可能在应用程序不运行的时候清理留在这个目录下的文件。有关如何获得这个目录路径的信息请参见“获取应用程序目录的路径”部分。 在iPhone OS 2.1及更高版本iTunes不对这个目录的内容进行备份。 备份和恢复 您不需要在应用程序中为备份和恢复操作做任何准备。在iPhone OS 2.2及更高版本的系统中当设备被连接到计算机并完成同步时iTunes会对除了下面这些目录之外的所有文件进行增量式的备份 Application_Home/AppName.app Application_Home/Library/Caches Application_Home/tmp 虽然iTunes确实对应用程序的程序包本身进行备份但并不是在每次同步时都进行这样的操作。通过设备上的App Store购买的应用程序在下一次设备和iTunes同步时进行备份。而在之后的同步操作中应用程序并不进行备份除非应用程序包本身发生了变化比如由于应用程序被更新了。 为了避免同步过程花费太长时间您应该有选择地往应用程序家目录中存放文件。Application_Home/Documents目录应该用于存放用户数据文件或不容易在应用程序中重新创建的文件。存储临时数据的文件应该放在Application Home/tmp目录而且应该在不需要的时候将其删除。如果您的应用程序需要创建用于下次启动的数据文件则应该将那些文件放到Application Home/Library/Caches目录下。 请注意如果您的应用程序需要创建数据量大或频繁变化的文件则应该考虑将它们存储在Application Home/Library/Caches目录下而不是Application_Home/Documents目录。备份大数据文件会使备份过程显著变慢备份频繁变化因此必须频繁备份的文件也同样如此。将这些文件放到Caches目录下可以避免每次同步都对其进行备份在iPhone OS 2.2及更高版本。 有关如何在应用程序中使用目录的更多信息请参见表6-1。 在应用程序更新过程中被保存的文件 更新应用程序就是将用户下载的新版应用程序代替之前的版本。在这个过程中iTunes会将更新过的应用程序安装到新的应用程序目录下并在删除老版本之前将用户数据文件转移到新的应用程序目录下。在更新的过程中iTunes保证如下目录中的文件会得以保留 Application_Home/Documents Application_Home/Library/Preferences 虽然其它用户目录下的文件也可能被转移但是您不应该假定更新之后该文件还仍然存在。 Keychain数据 keychain是一个安全、经过加密保护的容器用于保存密码和其它秘密信息。应用程序的keychain数据存储在应用程序沙箱之外。如果应用程序被卸载则该数据会自动被删除。当用户通过iTunes备份应用程序数据时keychain数据也会被备份。然而keychain数据只能被恢复到之前做备份的设备上。应用程序的更新并不影响其keychain数据。 有关iPhone OS keychain的更多信息请参见Keychain服务编程指南文档中的“Keychain服务的概念”部分。 获取应用程序目录的路径 系统在各个级别上都提供了用于获取应用程序沙箱目录路径的编程方法。然而取得这些路径的推荐方式还是使用Cocoa编程接口。NSHomeDirectory函数在Foundation框架中负责返回顶级家目录的路径—也就是包含应用程序、Documents、Library、和tmp目录的路径。除了这个函数您还可以用NSSearchPathForDirectoriesInDomains和NSTemporaryDirectory函数来取得Documents、Caches、和tmp目录的准确路径。 NSHomeDirectory和NSTemporaryDirectory函数都通过NSString对象返回正确格式的路径。您可以通过NSString类提供的与路径相关的方法来修改路径信息或创建新的路径字符串。举例来说在取得临时的目录路径之后您可以附加一个文件名并用结果字符串在临时目录下创建给定名称的文件。 请注意如果您使用带有ANSI C编程接口的框架—包括那些接受路径参数的接口—请记住NSString对象和其在Core Foundation框架中的等价类型之间是“免费桥接”的。这意味着您可以将一个NSString对象比如上述某个函数的返回结果强制类型转换为一个CFStringRef类型如下面的例子所示 CFStringRef homeDir (CFStringRef)NSHomeDirectory(); 有关免费桥接的更多信息请参见 Carbon-Cocoa集成指南文档。 Foundation框架中的NSSearchPathForDirectoriesInDomains函数用于取得几个应用程序相关目录的全路径。在iPhone OS上使用这个函数时第一个参数指定正确的搜索路径常量第二个参数则使用NSUserDomainMask常量。表6-2列出了大多数常用的常量及其返回的目录。 表6-2 常用的搜索路径常量 常量 目录 NSDocumentDirectory Application_Home/Documents NSCachesDirectory Application_Home/Library/Caches NSApplicationSupportDirectory Application_Home/Library/Application Support 由于NSSearchPathForDirectoriesInDomains函数最初是为Mac OS X设计的而Mac OS X上可能存在多个这样的目录所以它的返回值是一个路径数组而不是单一的路径。在iPhone OS上结果数组中应该只包含一个给定目录的路径。程序清单6-1显示了这个函数的典型用法。 程序清单6-1 取得指向应用程序Documents目录的文件系统路径 NSArray *paths NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory [paths objectAtIndex:0]; 在调用NSSearchPathForDirectoriesInDomains函数时您可以使用NSUserDomainMask之外的其它域掩码参数或者使用表6-2之外的其它目录常量但是应用程序不能向其返回的目录写入数据。举例来说如果您指定NSApplicationDirectory作为目录参数同时指定NSSystemDomainMask作为域掩码参数则可以返回设备上的/Applications路径但是您的应用程序不能往该位置写入任何文件。 另外一个需要记住的考虑是不同平台的目录位置是不一样的。NSSearchPathForDirectoriesInDomains、NSHomeDirectory、NSTemporaryDirectory、和其它类似函数的返回路径取决于应用程序运行在设备还是仿真器上。作为例子程序清单6-1上显示的函数调用在设备上返回的路径documentsDirectory大致如下 /var/mobile/Applications/30B51836-D2DD-43AA-BCB4-9D4DADFED6A2/Documents 但是它在仿真器上返回的路径则具有如下的形式 /Volumes/Stuff/Users/johnDoe/Library/Application Support/iPhone Simulator/User/Applications/118086A0-FAAF-4CD4-9A0F-CD5E8D287270/Documents 在读写用户偏好设置时请使用NSUserDefaults类或CFPreferences API。这些接口使您免于构造Library/Preferences/目录路径和直接读写偏好文件。有关使用这些接口的更多信息请参见“添加Settings程序包”部分。 如果应用程序的程序包中包含声音、图像、或其它资源则应该使用NSBundle类或CFBundleRef封装类型来装载那些资源。程序包知道应用程序内部资源应该在什么位置上此外它还知道用户的语言偏好能够自动选择本地化的资源。有关程序包的更多信息请参见“应用程序的程序包”部分。 文件数据的读写 iPhone OS提供了如下几种读、写、和管理文件的方法 Foundation框架: 如果您可以将应用程序数据表示为一个属性列表则可以用NSPropertyListSerialization API来将属性列表转换为一个NSData对象然后通过NSData类的方法将数据对象写入磁盘。 如果应用程序的模型对象采纳了NSCoding协议则可以通过NSKeyedArchiver类、特别是它的archivedDataWithRootObject:方法将模型对象图进行归档。 Foundation框架中的NSFileHandle类提供了随机访问文件内容的方法。 Foundation框架中的NSFileManager类提供了在文件系统中创建和操作文件的方法。 Core OS调用 诸如fopen、fread、和fwrite这些调用可以用于对文件进行顺序或随机读写。 mmap和munmap调用是将大文件载入内存并访问其内容的有效方法。 请注意上面的Core OS调用列表只是列举一些较为常用的例子。更完全的可用函数列表请参见iPhone OS手册的第三部分中的函数列表。 本章的下面部分将描述如何使用一些高级技术来进行文件的读写。有关Foundation框架中与文件相关类的更多信息请参见Foundation框架参考。 属性列表数据的读写 属性列表是一种数据表示形式用于封装几种Foundation及 Core Foundation的数据类型包括字典、数组、字符串、日期、二进制数据、数值及布尔值。属性列表通常用于存储结构化的配置数据。举例来说每个Cocoa和iPhone应用程序中都有一个Info.plist文件它就是用于存储应用程序本身配置信息的属性列表。您自己也可以用属性列表来存储其它信息比如应用程序退出时的状态等。 在代码中属性列表的构造通常从构造一个字典或数组、并将它作为容器对象开始然后在容器中加入其它的属性列表对象可能包含其它的字典和数组。字典的键必须是字符串对象键的值则是NSDictionary、NSArray、NSString、NSDate、NSData、和NSNumber类的实例。 对于可以将数据表示为属性列表对象的应用程序比如NSDictionary对象您可以用程序清单6-2所示的方法来将属性列表写入磁盘。该方法将属性列表序列化为NSData对象然后调用writeApplicationData:toFile:方法其实现如程序清单6-4所示将数据写入磁盘。 程序清单6-2 将属性列表对象转换为NSData对象并写入存储 - (BOOL)writeApplicationPlist:(id)plist toFile:(NSString *)fileName { NSString *error; NSData *pData [NSPropertyListSerialization dataFromPropertyList:plist format:NSPropertyListBinaryFormat_v1_0 errorDescription:error]; if (!pData) { NSLog(%, error); return NO; } return ([self writeApplicationData:pData toFile:(NSString *)fileName]); } 在iPhone OS系统上保存属性列表文件时采用二进制格式进行存储是很重要的。在编码时可以通过为dataFromPropertyList:format:errorDescription:方法的format 参数指定NSPropertyListBinaryFormat_v1_0值来实现。二进制格式比其它基于文本的格式紧凑得多这种紧凑不仅使属性列表在用户设备上占用的空间最小还可以减少读写属性列表的时间。 程序清单6-3的代码展示了如何从磁盘装载属性列表并重新生成属性列表中的对象。 程序清单 6-3 从应用程序的Documents目录读取属性列表对象 - (id)applicationPlistFromFile:(NSString *)fileName { NSData *retData; NSString *error; id retPlist; NSPropertyListFormat format; retData [self applicationDataFromFile:fileName]; if (!retData) { NSLog(Data file not returned.); return nil; } retPlist [NSPropertyListSerialization propertyListFromData:retData mutabilityOption:NSPropertyListImmutable format:format errorDescription:error]; if (!retPlist){ NSLog(Plist not returned, error: %, error); } return retPlist; } 有关属性列表和NSPropertyListSerialization类的更多信息请参见属性列表编程指南。 用归档器进行数据读写 归档器的作用是将任意的对象集合转换为字节流。这听起来像是NSPropertyListSerialization类采用的过程但它们之间有一个重要的区别。属性列表序列化只能转换一个有限集合的数据类型大多数是数量类型而归档器可以转换任意的Objective-C对象、数量类型、数组、结构、字符串、及更多其它类型。 归档过程的关键在于目标对象的本身。归档器操作的对象必须遵循NSCoding协议该协议定义了读写对象状态的接口。归档器在编码一组对象时会向每个对象发送一个encodeWithCoder:消息目标对象则在这个方法中将自身的关键状态信息写入到对应的档案中。解档过程的信息流与此相反在解档过程中每个对象都会接收到一个initWithCoder:消息用于从档案中读取当前状态信息并基于这些信息进行初始化。解档过程完成后字节流就被重新组成一组与之前写入档案时具有相同状态的新对象。 Foundation框架支持两种归档器—顺序归档和基于键的归档。基于键的归档器更加灵活是应用程序开发中推荐使用的归档器。下面的例子显示如何用一个基于键的归档器对一个对象图进行归档。_myDataSource对象的representation方法返回一个单独的对象可能是一个数组或字典指向将要包含到档案中的所有对象之后该数据对象就被写入由myFilePath变量指定路径的文件中。 NSData *data [NSKeyedArchiver archivedDataWithRootObject:[_myDataSource representation]]; [data writeToFile:myFilePath atomically:YES]; 请注意您还可以向NSKeyedArchiver对象发送archiveRootObject:toFile:消息以便在一个步骤中完成档案的创建和将档案写入存储。 您可以简单地通过相反的流程来装载磁盘上的档案内容。在装载磁盘数据之后可以通过NSKeyedUnarchiver类及其unarchiveObjectWithData:类方法来取回模型对象图。例如您可以用下面的代码来解档之前例子中的数据 NSData* data [NSData dataWithContentsOfFile:myFilePath]; id rootObject [NSKeyedUnarchiver unarchiveObjectWithData:data]; 更多如何使用归档器和如何使对象支持NSCoding协议的信息请参见Cocoa的归档和序列化编程指南。 将数据写到Documents目录 有了封装应用程序数据的NSData对象或者是档案或者是序列化了的属性列表之后您就可以调用程序清单6-4所示的方法来将数据写到应用程序的Documents目录中。 程序清单6-4 将数据写到应用程序的Documents目录 - (BOOL)writeApplicationData:(NSData *)data toFile:(NSString *)fileName { NSArray *paths NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory [paths objectAtIndex:0]; if (!documentsDirectory) { NSLog(Documents directory not found!); return NO; } NSString *appFile [documentsDirectory stringByAppendingPathComponent:fileName]; return ([data writeToFile:appFile atomically:YES]); } 从Documents目录读取数据 为了从应用程序的Documents目录读取文件您首先需要根据文件名构建相应的路径然后以期望的方法将文件内容读入内存。对于相对较小的文件—也就是尺寸小于几个内存页面的文件—您可以用程序清单6-5中的代码来取得文件内容。该代码首先为Documents目录下的文件构建一个全路径并为这个路径创建一个数据对象然后返回。 程序清单6-5 从应用程序的Documents目录读取数据 - (NSData *)applicationDataFromFile:(NSString *)fileName { NSArray *paths NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory [paths objectAtIndex:0]; NSString *appFile [documentsDirectory stringByAppendingPathComponent:fileName]; NSData *myData [[[NSData alloc] initWithContentsOfFile:appFile] autorelease]; return myData; } 对于载入时需要多个内存页面的文件应该避免一次性地装载整个文件。如果您只是计划使用部分文件这一点就尤其重要。对于大文件您应该考虑用mmap函数或NSData的initWithContentsOfMappedFile:方法来将文件映射到内存。 到底是采用映射文件还是直接装载取决于您的考虑。如果只需要少量3-4内存页面则将整个文件载入内存相对安全一些。但是如果您的文件需要数十或上百个页面则将文件映射到内存可能更为有效一些。当然无论采用什么方法您都应该测量应用程序的性能确定装载文件和为其分配必要内存需要多长时间。 文件访问的指导原则 在您创建文件或写入文件数据时请记住下面这些指导原则 使写入磁盘的数据量尽可能少。文件操作速度相对较慢且涉及到Flash盘的写操作有一定的寿命限制。下面这些具体的小贴士可以帮助您最少化与文件相关的操作 只写入发生变化的文件部分但要尽可能对变化进行累计避免在只有少数字节发生改变时对整个文件进行写操作。 在定义文件格式时将频繁变化的内容放在一起以便使每次需要写入磁盘的总块数最少。 如果您的数据是需要随机访问的结构化内容则可以将它们存储在Core Data持久仓库或SQLite数据库中。如果您处理的数据量可能增长到数兆以上这一点尤其重要。 避免将缓存文件写入磁盘。这个原则的唯一例外是在应用程序退出时您需要写入某些状态信息使程序在下次启动时可以回到之前的状态。 保存状态信息 当用户按下Home键时iPhone OS会退出您的应用程序返回到Home屏幕。类似地如果您的应用程序打开一个由其它应用程序处理的URI模式iPhone OS也会退出您的应用程序在相应的应用程序上打开该URI。换句话说在Mac OS X上引起应用程序挂起或转向后台的动作在iPhone OS上都会使其退出。这些动作在移动设备上经常发生因此您的应用程序必须改变管理可变数据和程序状态的方式。 大多数桌面应用程序由用户手工选择将文件存入磁盘的时机与此不同的是iPhone应用程序应该在工作流的关键点上自动保存已发生的变化。究竟何时保存数据由您自己来决定但是有两个潜在的时间点或者在用户做出改变之后马上进行保存或者将同一页面上的变化累计成批然后在退出该页面、显示新页面、或者应用程序退出的时候进行保存。在任何情况下您不应该让用户漫游到新的页面而不保存之前页面的内容。 当您的应用程序被要求退出时应该将当前状态保持到临时的缓存文件或偏好数据库中。在用户下次启动应用程序时可以根据这些信息将程序恢复到之前的状态。您保持的状态信息应该尽可能少但同时又足够使应用程序恢复到恰当的点。您不必一定要显示用户上次退出时操作的页面如果那样做并不合理的话。比如如果一个用户在编辑某个联系人的时候离开了Phone程序那么在下次运行时Phone程序显示的是联系人的顶级列表而不是该联系人的编辑屏幕。 大小写敏感性 iPhone OS设备的文件系统是大小写敏感的。在处理文件名的任何时候您都应该确保大小写准确匹配否则可能不能打开或访问文件。