NSFileManager
NSFile
是处理文件系统的 Foundation 框架的高级API。它抽象了 Unix 和 Finder 的内部构成,和 iCloud ubiquitous containers 一样, 提供了创建,读取,移动,拷贝以及删除本地或者网络驱动器上的文件或者目录的方法。
文件系统是一个复杂的主题,它有数十年的历史,一些遗留下的复杂性和一些特别的地方,已经不是一篇文章就可以描述的了。现在大多数的应用除了简单的文件操作之外不会经常与文件系统交互,所以有时候简单了解它的基础就行了。
你可以复制粘贴下面的代码试试看,用他们作为你的代码基础,修改这些参数来达到你期望的效果。
常用操作
纵观苹果提供的样例代码,尽是这样的黑魔法: NSSearch
, 它或许绑定了KVO,也是Cocoa最糟糕的API之一。你只需要知道它返回了一个包含用户文档目录作为第一个元素的数组就行了。真要感谢 NSArray -first
。
确定文件是否存在
NSFile Manager *file Manager = [NSFile Manager default Manager];
NSString *documents Path = [NSSearch Path For Directories In Domains(NSDocument Directory, NSUser Domain Mask, YES) first Object];
NSString *file Path = [documents Path string By Appending Path Component:@"file.txt"];
BOOL file Exists = [file Manager file Exists At Path:file Path];
列出目录里面的所有文件
NSFile Manager *file Manager = [NSFile Manager default Manager];
NSURL *bundle URL = [[NSBundle main Bundle] bundle URL];
NSArray *contents = [file Manager contents Of Directory At URL:bundle URL
including Properties For Keys:@[]
options:NSDirectory Enumeration Skips Hidden Files
error:nil];
NSPredicate *predicate = [NSPredicate predicate With Format:@"path Extension == 'png'"];
for (NSURL *file URL in [contents filtered Array Using Predicate:predicate]) {
// 在目录中枚举 .png 文件
}
在目录中递归地遍历文件
NSFile Manager *file Manager = [NSFile Manager default Manager];
NSURL *bundle URL = [[NSBundle main Bundle] bundle URL];
NSDirectory Enumerator *enumerator = [file Manager enumerator At URL:bundle URL
including Properties For Keys:@[NSURLName Key, NSURLIs Directory Key]
options:NSDirectory Enumeration Skips Hidden Files
error Handler:^BOOL(NSURL *url, NSError *error)
{
if (error) {
NSLog(@"[Error] %@ (%@)", error, url);
return NO;
}
return YES;
}];
NSMutable Array *mutable File URLs = [NSMutable Array array];
for (NSURL *file URL in enumerator) {
NSString *filename;
[file URL get Resource Value:&filename for Key:NSURLName Key error:nil];
NSNumber *is Directory;
[file URL get Resource Value:&is Directory for Key:NSURLIs Directory Key error:nil];
// Skip directories with '_' prefix, for example
if ([filename has Prefix:@"_"] && [is Directory bool Value]) {
[enumerator skip Descendants];
continue;
}
if (![is Directory bool Value]) {
[mutable File URLs add Object:file URL];
}
}
创建一个目录
NSFile Manager *file Manager = [NSFile Manager default Manager];
NSString *documents Path = [NSSearch Path For Directories In Domains(NSDocument Directory, NSUser Domain Mask, YES) first Object];
NSString *images Path = [documents Path string By Appending Path Component:@"images"];
if (![file Manager file Exists At Path:images Path]) {
[file Manager create Directory At Path:images Path with Intermediate Directories:NO attributes:nil error:nil];
}]
删除一个目录
NSFile Manager *file Manager = [NSFile Manager default Manager];
NSString *documents Path = [NSSearch Path For Directories In Domains(NSDocument Directory, NSUser Domain Mask, YES) first Object];
NSString *file Path = [documents Path string By Appending Path Component:@"image.png"];
NSError *error = nil;
if (![file Manager remove Item At Path:file Path error:&error]) {
NSLog(@"[Error] %@ (%@)", error, file Path);
}
删除文件的创建日期
NSFile Manager *file Manager = [NSFile Manager default Manager];
NSString *documents Path = [NSSearch Path For Directories In Domains(NSDocument Directory, NSUser Domain Mask, YES) first Object];
NSString *file Path = [documents Path string By Appending Path Component:@"Document.pages"];
NSDate *creation Date = nil;
if ([file Manager file Exists At Path:file Path]) {
NSDictionary *attributes = [file Manager attributes Of Item At Path:file Path error:nil];
creation Date = attributes[NSFile Creation Date];
}
通过NSFileManager的 -attributes
和其它方法可以访问很多文件的属性
文件属性的键
NSFile
: 文件是否只读Append Only NSFile
: 文件是否繁忙Busy NSFile
: 文件创建日期Creation Date NSFile
: 文件所有者的名字Owner Account Name NSFile
: 文件所有组的名字Group Owner Account Name NSFile
: 文件所在驱动器的标示符Device Identifier NSFile
: 文件后缀是否隐藏Extension Hidden NSFile
: 文件所有组的group IDGroup Owner Account ID NSFile
: 文件的HFS创建者的代码HFSCreator Code NSFile
: 文件的HFS类型代码HFSType Code NSFile
: 文件是否可以改变Immutable NSFile
: 文件修改日期Modification Date NSFile
: 文件所有者的IDOwner Account ID NSFile
: 文件的Posix权限Posix Permissions NSFile
: 文件的链接数量Reference Count NSFile
: 文件的字节Size NSFile
: 文件在文件系统的文件数量System File Number NSFile
: 文件类型Type NSDirectory
: 浅层的枚举,不会枚举子目录Enumeration Skips Subdirectory Descendants NSDirectory
: 不会扫描pakages的内容Enumeration Skips Package Descendants NSDirectory
: 不会扫描隐藏文件Enumeration Skips Hidden File
NSFileManagerDelegate
NSFileManager 可以设置一个 <NSFile
protocol 来确认是否要进行特定的文件操作。它允许进行一些业务逻辑,比如保护一些文件删除,在 Controller 中删除一些元素
NSFile
里面有四个方法,每个按照path变化
-file
Manager:should Move Item At URL:to URL: -file
Manager:should Copy Item At URL:to URL: -file
Manager:should Remove Item At URL: -file
Manager:should Link Item At URL:to URL:
如果你想用 alloc init
初始化你自己的 NSFile
来取代shared实例,那就要用它了,就像文档说的
如果你使用一个delegate 来接受移动,拷贝,涉案出,以及链接的操作,你需要创建一个独一无二的实例,将delegate绑定到你的实例中,用这个fielmanager开始你的操作
NSFile Manager *file Manager = [[NSFile Manager alloc] init];
file Manager.delegate = delegate;
NSURL *bundle URL = [[NSBundle main Bundle] bundle URL];
NSArray *contents = [file Manager contents Of Directory At URL:bundle URL
including Properties For Keys:@[]
options:NSDirectory Enumeration Skips Hidden Files
error:nil];
for (NSString *file Path in contents) {
[file Manager remove Item At Path:file Path error:nil];
}
CustomFileManagerDelegate.m
#pragma mark - NSFile Manager Delegate
- (BOOL)file Manager:(NSFile Manager *)file Manager
should Remove Item At URL:(NSURL *)URL
{
return ![[[URL last Path Component] path Extension] is Equal To String:@"pdf"];
}
Ubiquitous Storage
文档也可与放到iCloud里面。如果你猜可以直截了当的进行操作,恭喜你猜对了。
这里有一个其它用到 alloc init
的地方,因为 URLFor
是代码块调用,所以整个操作需要在后台队列分发
将文件放到iCloud里面
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSFile Manager *file Manager = [[NSFile Manager alloc] init];
NSString *documents Path = [NSSearch Path For Directories In Domains(NSDocument Directory, NSUser Domain Mask, YES) first Object];
NSURL *file URL = [NSURL file URLWith Path:[documents Path string By Appending Path Component:@"Document.pages"]];
//这里的 identifier 应该设置为 entitlements 的第一个元素;当你使用这段代码的时候需要把 identifier 设置为你自己的真实 identifier
NSString *identifier = nil;
NSURL *ubiquitous Container URL = [file Manager URLFor Ubiquity Container Identifier:identifier];
NSURL *ubiquitous File URL = [ubiquitous Container URL URLBy Appending Path Component:@"Document.pages"];
NSError *error = nil;
BOOL success = [file Manager set Ubiquitous:YES
item At URL:file URL
destination URL:ubiquitous File URL
error:&error];
if (!success) {
NSLog(@"[Error] %@ (%@) (%@)", error, file URL, ubiquitous File URL);
}
});
你可以在苹果的
i
文档里面找到更多信息Cloud File Management
关于文件系统需要知道很多东西,但大多数是理论测验层面的。别误会,这些理论测验并没有错!但理论并不能教你代码该怎么写。NSFileManager可以让你不用学习它们大多数的内容就能完成工作。