iOS 当中的数据一般都存放在三个目录里,Documents,Library,tmp
Documents:用户生成的文件、其他数据及其他程序不能重新创建的文件,iTunes备份和恢复的时候会包括此目录
Library:主要使用它的子文件夹,我们熟悉的NSUserDefaults就存在于它的子目录中。
Library/Caches:存放缓存文件,iTunes不会备份此目录,此目录下文件不会在应用退出删除,“删除缓存”一般指的就是清除此目录下的文件。
Library/Preferences:NSUserDefaults的数据存放于此目录下。
tmp:只是临时使用的数据,iTunes不会备份和恢复此目录,此目录下文件可能会在应用退出后删除。App应当负责在不需要使用的时候清理这些文件,系统在App不运行的时候也可能清理这个目录。
- (NSString *)getDocumetsPath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return paths[0];
}
- (NSString *)getLibraryPath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
return paths[0];
}
- (NSString *)getCachesPath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
return paths[0];
}
- (NSString *)tmpPath {
NSString *path = NSTemporaryDirectory();
return path;
}
//创建目录
- (NSString *)createFolder:(NSString *)fileName {
NSString *documentsPath = [self getDocumetsPath];
NSString *folderPath = [documentsPath stringByAppendingPathComponent:fileName];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL isEixt = NO;
if ([fileManager fileExistsAtPath:folderPath isDirectory:&isEixt]) {//判断路径是否存在
return folderPath;
} else {
BOOL isSuccess = [fileManager createDirectoryAtPath:folderPath withIntermediateDirectories:YES attributes:nil error:nil]; //创建文件路径
if (isSuccess) {
return folderPath;
} else {
return nil;
}
}
}
//创建文件
- (BOOL)createFile:(NSString *)filePath {
NSString *path = [filePath stringByAppendingString:@"test.txt"];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL isSuccess = [fileManager createFileAtPath:path contents:nil attributes:nil];
if (isSuccess) {
return YES;
} else {
return NO;
}
}
//写入文件
- (BOOL)writeToFile:(NSString *)filePath {
NSString *test = @"";
BOOL isSuccess = [test writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
return isSuccess;
}
//文件属性
-(void)fileAttriutes:(NSString *)filePath{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSDictionary *fileAttributes = [fileManager attributesOfItemAtPath:filePath error:nil];
NSArray *keys;
id key, value;
keys = [fileAttributes allKeys];
NSInteger count = [keys count];
for (NSInteger i = 0; i < count; i++) {
key = [keys objectAtIndex: i]; //文件名
value = [fileAttributes objectForKey: key]; //文件属性
}
}
//删除文件路径
- (BOOL)deleteFileByPath:(NSString *)path {
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL res = [fileManager removeItemAtPath:path error:nil];
NSLog(@"文件是否存在: %@",[fileManager isExecutableFileAtPath:path]?@"YES":@"NO");
return res;
}
//复制文件
- (BOOL)copyFile:(NSString *)path topath:(NSString *)topath {
BOOL result = NO;
NSError * error = nil;
result = [[NSFileManager defaultManager]copyItemAtPath:path toPath:topath error:&error ];
if (error){
NSLog(@"copy失败:%@",[error localizedDescription]);
}
return result;
}
//剪切移动文件
+ (BOOL)cutFile:(NSString *)path topath:(NSString *)topath {
BOOL result = NO;
NSError * error = nil;
result = [[NSFileManager defaultManager]moveItemAtPath:path toPath:topath error:&error ];
if (error){
NSLog(@"cut失败:%@",[error localizedDescription]);
}
return result;
}
//得到磁盘缓存的大小
- (NSUInteger)getSize:(NSString *)filePath {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSUInteger size = 0;
NSDirectoryEnumerator *fileEnumerator = [fileManager enumeratorAtPath:filePath];
for (NSString *fileName in fileEnumerator) {
NSString *filePaths = [filePath stringByAppendingPathComponent:fileName];
NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:filePaths error:nil];
size += [attrs fileSize];
}
return size;
}
//获取磁盘中文件数量
- (NSUInteger)getDiskCount:(NSString *)filePath {
NSFileManager *fileManager = [NSFileManager defaultManager];
__block NSUInteger count = 0;
dispatch_sync(dispatch_queue_create("xq_test", DISPATCH_QUEUE_CONCURRENT), ^{
NSDirectoryEnumerator *fileEnumerator = [fileManager enumeratorAtPath:filePath];
count = fileEnumerator.allObjects.count;
});
return count;
}
//异步计算磁盘缓存的大小
- (void)calculateSize:(NSString *)filePath {
NSURL *diskCacheURL = [NSURL fileURLWithPath:filePath isDirectory:YES];
NSFileManager *fileManager = [NSFileManager defaultManager];
dispatch_async(dispatch_queue_create("xq_test", DISPATCH_QUEUE_CONCURRENT), ^{
NSUInteger fileCount = 0;
NSUInteger totalSize = 0;
NSDirectoryEnumerator *fileEnumerator = [fileManager enumeratorAtURL:diskCacheURL
includingPropertiesForKeys:@[NSFileSize]
options:NSDirectoryEnumerationSkipsHiddenFiles
errorHandler:NULL];
for (NSURL *fileURL in fileEnumerator) {
NSNumber *fileSize;
[fileURL getResourceValue:&fileSize forKey:NSURLFileSizeKey error:NULL];
totalSize += fileSize.unsignedIntegerValue;
fileCount += 1;
}
NSLog(@"fileCount:%lu totalSize:%lu",(unsigned long)fileCount,(unsigned long)totalSize);
});
}
//异步清除所有失效的缓存图片-因为可以设定缓存时间,超过则失效
- (void)deleteOldFilesWithCompletionBlock:(nullable SDWebImageNoParamsBlock)completionBlock {
dispatch_async(self.ioQueue, ^{
NSURL *diskCacheURL = [NSURL fileURLWithPath:self.diskCachePath isDirectory:YES];
//resourceKeys数组包含遍历文件的属性,NSURLIsDirectoryKey判断遍历到的URL所指对象是否是目录,
//NSURLContentModificationDateKey判断遍历返回的URL所指项目的最后修改时间,NSURLTotalFileAllocatedSizeKey判断URL目录中所分配的空间大小
NSArray *resourceKeys = @[NSURLIsDirectoryKey, NSURLContentModificationDateKey, NSURLTotalFileAllocatedSizeKey];
// This enumerator prefetches useful properties for our cache files.
//利用目录枚举器遍历指定磁盘缓存路径目录下的文件,从而我们活的文件大小,缓存时间等信息
NSDirectoryEnumerator *fileEnumerator = [_fileManager enumeratorAtURL:diskCacheURL
includingPropertiesForKeys:resourceKeys
options:NSDirectoryEnumerationSkipsHiddenFiles
errorHandler:NULL];
//计算过期时间,默认1周以前的缓存文件是过期失效
NSDate *expirationDate = [NSDate dateWithTimeIntervalSinceNow:-self.config.maxCacheAge];
//保存遍历的文件url
NSMutableDictionary *> *cacheFiles = [NSMutableDictionary dictionary];
//保存当前缓存的大小
NSUInteger currentCacheSize = 0;
// Enumerate all of the files in the cache directory. This loop has two purposes:
//
// 1. Removing files that are older than the expiration date.
// 2. Storing file attributes for the size-based cleanup pass.
//保存删除的文件url
NSMutableArray *urlsToDelete = [[NSMutableArray alloc] init];
//遍历目录枚举器,目的1删除过期文件 2纪录文件大小,以便于之后删除使用
for (NSURL *fileURL in fileEnumerator) {
NSError *error;
//获取指定url对应文件的指定三种属性的key和value
NSDictionary *resourceValues = [fileURL resourceValuesForKeys:resourceKeys error:&error];
// Skip directories and errors.
//如果是文件夹则返回
if (error || !resourceValues || [resourceValues[NSURLIsDirectoryKey] boolValue]) {
continue;
}
// Remove files that are older than the expiration date;
//获取指定url文件对应的修改日期
NSDate *modificationDate = resourceValues[NSURLContentModificationDateKey];
//如果修改日期大于指定日期,则加入要移除的数组里
if ([[modificationDate laterDate:expirationDate] isEqualToDate:expirationDate]) {
[urlsToDelete addObject:fileURL];
continue;
}
// Store a reference to this file and account for its total size.
//获取指定的url对应的文件的大小,并且把url与对应大小存入一个字典中
NSNumber *totalAllocatedSize = resourceValues[NSURLTotalFileAllocatedSizeKey];
currentCacheSize += totalAllocatedSize.unsignedIntegerValue;
cacheFiles[fileURL] = resourceValues;
}
//删除所有最后修改日期大于指定日期的所有文件
for (NSURL *fileURL in urlsToDelete) {
[_fileManager removeItemAtURL:fileURL error:nil];
}
// If our remaining disk cache exceeds a configured maximum size, perform a second
// size-based cleanup pass. We delete the oldest files first.
//如果当前缓存的大小超过了默认大小,则按照日期删除,直到缓存大小<默认大小的一半
if (self.config.maxCacheSize > 0 && currentCacheSize > self.config.maxCacheSize) {
// Target half of our maximum cache size for this cleanup pass.
const NSUInteger desiredCacheSize = self.config.maxCacheSize / 2;
// Sort the remaining cache files by their last modification time (oldest first).
//根据文件创建的时间排序
NSArray *sortedFiles = [cacheFiles keysSortedByValueWithOptions:NSSortConcurrent
usingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1[NSURLContentModificationDateKey] compare:obj2[NSURLContentModificationDateKey]];
}];
// Delete files until we fall below our desired cache size.
//迭代删除缓存,直到缓存大小是默认缓存大小的一半
for (NSURL *fileURL in sortedFiles) {
if ([_fileManager removeItemAtURL:fileURL error:nil]) {
NSDictionary *resourceValues = cacheFiles[fileURL];
NSNumber *totalAllocatedSize = resourceValues[NSURLTotalFileAllocatedSizeKey];
currentCacheSize -= totalAllocatedSize.unsignedIntegerValue;
if (currentCacheSize < desiredCacheSize) {
break;
}
}
}
}
if (completionBlock) {
dispatch_async(dispatch_get_main_queue(), ^{
completionBlock();
});
}
});
}
- (unsigned long long)fileSize; //文件大小
- (NSDate *)fileModificationDate; //文件的修改时间
- (NSString *)fileType; //文件类型
- (NSUInteger)filePosixPermissions;
- (NSString *)fileOwnerAccountName; //文件拥有者
- (NSString *)fileGroupOwnerAccountName;
- (NSInteger)fileSystemNumber;
- (NSUInteger)fileSystemFileNumber;
- (BOOL)fileExtensionHidden;
- (OSType)fileHFSCreatorCode;
- (OSType)fileHFSTypeCode;
- (BOOL)fileIsImmutable;
- (BOOL)fileIsAppendOnly;
- (NSDate *)fileCreationDate; //创建时间
- (NSNumber *)fileOwnerAccountID;
- (NSNumber *)fileGroupOwnerAccountID;