iOS 關(guān)于文件操作 NSFileManager

[TOC]
相關(guān)知識
--

沙盒機(jī)制

每一個(gè)iOS應(yīng)用程序都會(huì)為自己創(chuàng)建一個(gè)文件系統(tǒng)目錄,這個(gè)獨(dú)立、封閉、安全的空間叫做沙盒。沙盒就是一種安全體系,它規(guī)定了應(yīng)用程序只能在自己的文件系統(tǒng)目錄內(nèi)訪問文件,不可以訪問其他應(yīng)用沙盒內(nèi)的內(nèi)容。所有的非代碼文件都保存在這個(gè)地方。

沙盒根目錄結(jié)構(gòu):Documents、Library、temp

沙盒目錄

Documents

保存應(yīng)用運(yùn)行時(shí)生成的需要持久化的數(shù)據(jù),iTunes備份和恢復(fù)的時(shí)候會(huì)包括此目錄,所以蘋果建議將程序中建立的或在程序中瀏覽到的文件數(shù)據(jù)保存在該目錄下。

Library

  • Caches:存放緩存文件,iTunes不會(huì)備份此目錄,此目錄下文件不會(huì)在應(yīng)用退出后刪除 。一般存放體積比較大,不是特別重要的資源。
  • Preferences:保存APP的所有偏好設(shè)置,iOS的Settings(設(shè)置)應(yīng)用會(huì)在該目錄中查找應(yīng)用的設(shè)置信息,iTunes會(huì)自動(dòng)備份該目錄。注意:通過NSUserDefaults類來讀取和設(shè)置。

tmp

保存應(yīng)用運(yùn)行時(shí)所需的臨時(shí)數(shù)據(jù),這個(gè)可以放一些當(dāng)APP退出后不再需要的文件。應(yīng)用沒有運(yùn)行時(shí),系統(tǒng)也有可能會(huì)清除該目錄下的文件,iTunes不會(huì)同步該目錄。iPhone重啟時(shí),該目錄下的文件會(huì)被刪除。

如何查看該目錄?

XCode->Window->Devices->真機(jī)->Installed Apps->應(yīng)用->ShowContainer

沙盒目錄

也可以點(diǎn)擊DownloadContainer下載該沙盒文件查看內(nèi)容

沙盒內(nèi)容

獲取相關(guān)目錄

// 獲取Document目錄
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
 
// 獲取Library目錄
NSString *LibraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
 
// 獲取Caches目錄
NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
 
// 獲取Preferences目錄 通常情況下,Preferences有系統(tǒng)維護(hù),所以我們很少去操作它。
NSString *preferPath = [LibraryPath stringByAppendingPathComponent:@"Preferences"];

// 獲取tmp目錄
NSString *tmpPath = NSTemporaryDirectory();

[toc]
相關(guān)文件操作
--

  • 創(chuàng)建文件夾
+(BOOL)creatDir:(NSString *)path{
    if (path.length==0) {
        return NO;
    }
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL isSuccess = YES;
    BOOL isExist = [fileManager fileExistsAtPath:path];
    if (isExist==NO) {
        NSError *error;
        if (![fileManager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:&error]) {
            isSuccess = NO;
            NSLog(@"creat Directory Failed:%@",[error localizedDescription]);
        }
    }
    return isSuccess;
}
  • 創(chuàng)建文件
+(BOOL)creatFile:(NSString*)filePath{
    if (filePath.length==0) {
        return NO;
    }
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if ([fileManager fileExistsAtPath:filePath]) {
        return YES;
    }
    NSError *error;
    NSString *dirPath = [filePath stringByDeletingLastPathComponent];
    BOOL isSuccess = [fileManager createDirectoryAtPath:dirPath withIntermediateDirectories:YES attributes:nil error:&error];
    if (error) {
        NSLog(@"creat File Failed:%@",[error localizedDescription]);
    }
    if (!isSuccess) {
        return isSuccess;
    }
    isSuccess = [fileManager createFileAtPath:filePath contents:nil attributes:nil];
    return isSuccess;
}
  • 寫數(shù)據(jù)
+(BOOL)writeToFile:(NSString*)filePath contents:(NSData *)data{
    if (filePath.length==0) {
        return NO;
    }
    BOOL result = [self creatFile:filePath];
    if (result) {
        if ([data writeToFile:filePath atomically:YES]) {
            NSLog(@"write Success");
        }else{
            NSLog(@"write Failed");
        }
    }
    else{
        NSLog(@"write Failed");
    }
    return result;
}
  • 追加寫數(shù)據(jù)
+(BOOL)appendData:(NSData*)data withPath:(NSString *)filePath{
    if (filePath.length==0) {
        return NO;
    }
    BOOL result = [self creatFile:filePath];
    if (result) {
        NSFileHandle *handle = [NSFileHandle fileHandleForWritingAtPath:filePath];
        [handle seekToEndOfFile];
        [handle writeData:data];
        [handle synchronizeFile];
        [handle closeFile];
    }
    else{
        NSLog(@"appendData Failed");
    }
    return result;
}
  • 讀文件數(shù)據(jù)
+(NSData*)readFileData:(NSString *)path{
    NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
    NSData *fileData = [handle readDataToEndOfFile];
    [handle closeFile];
    return fileData;
}
  • 獲取文件夾下所有的文件列表
+(NSArray*)getFileList:(NSString*)path{
    if (path.length==0) {
        return nil;
    }
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error;
    NSArray *fileList = [fileManager contentsOfDirectoryAtPath:path error:&error];
    if (error) {
        NSLog(@"getFileList Failed:%@",[error localizedDescription]);
    }
    return fileList;
}
  • 獲取文件夾下所有文件(深度遍歷)
+(NSArray*)getAllFileList:(NSString*)path{
    if (path.length==0) {
        return nil;
    }
    NSArray *fileArray = [self getFileList:path];
    NSMutableArray *fileArrayNew = [NSMutableArray array];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    for (NSString *aPath in fileArray) {
        NSString * fullPath = [path stringByAppendingPathComponent:aPath];
        BOOL isDir = NO;
        if ([fileManager fileExistsAtPath:fullPath isDirectory:&isDir]) {
            if (isDir) {
                [fileArrayNew addObjectsFromArray:[self getAllFileList:fullPath]];
            }else{
                [fileArrayNew addObject:fullPath];
            }
        }
    }
    return fileArrayNew;
}
  • 移動(dòng)文件
+(BOOL)moveFile:(NSString *)fromPath toPath:(NSString *)toPath toPathIsDir:(BOOL)dir{
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if (![fileManager fileExistsAtPath:fromPath]) {
        NSLog(@"Error: fromPath Not Exist");
        return NO;
    }
    BOOL isDir = NO;
    BOOL isExist = [fileManager fileExistsAtPath:toPath isDirectory:&isDir];
    if (isExist) {
        if (isDir) {
            if ([self creatDir:toPath]) {
                NSString *fileName = fromPath.lastPathComponent;
                toPath = [toPath stringByAppendingPathComponent:fileName];
                return [self moveItemAtPath:fromPath toPath:toPath];
            }
        }else{
            [self removeFile:toPath];
            return [self moveItemAtPath:fromPath toPath:toPath];
        }
    }
    else{
        if (dir) {
            if ([self creatDir:toPath]) {
                NSString *fileName = fromPath.lastPathComponent;
                toPath = [toPath stringByAppendingPathComponent:fileName];
                return [self moveItemAtPath:fromPath toPath:toPath];
            }
        }else{
            return [self moveItemAtPath:fromPath toPath:toPath];
        }
    }
    return NO;
}
+(BOOL)moveItemAtPath:(NSString*)fromPath toPath:(NSString*)toPath{
    BOOL result = NO;
    NSError * error = nil;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    result = [fileManager moveItemAtPath:fromPath toPath:toPath error:&error];
    if (error){
        NSLog(@"moveFile Fileid:%@",[error localizedDescription]);
    }
    return result;
}
  • 刪除文件
+(BOOL)removeFile:(NSString*)filePath{
    BOOL isSuccess = NO;
    NSError *error;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    isSuccess = [fileManager removeItemAtPath:filePath error:&error];
    if (error) {
        NSLog(@"removeFile Field:%@",[error localizedDescription]);
    }else{
        NSLog(@"removeFile Success");
    }
    return isSuccess;
}
  • 刪除文件夾
+(BOOL)removeDir:(NSString*)path{
    return [self removeFile:path];
}
  • 刪除某些后綴的文件
+(void)removeFileSuffixList:(NSArray<NSString*>*)suffixList filePath:(NSString*)path deep:(BOOL)deep{
    NSArray *fileArray = nil;
    if (deep) {  // 是否深度遍歷
        fileArray = [self getAllFileList:path];
    }else{
        fileArray = [self getFileList:path];
        NSMutableArray *fileArrayTmp = [NSMutableArray array];
        for (NSString *fileName in fileArray) {
            NSString* allPath = [path stringByAppendingPathComponent:fileName];
            [fileArrayTmp addObject:allPath];
        }
        fileArray = fileArrayTmp;
    }
    for (NSString *aPath in fileArray) {
        for (NSString* suffix in suffixList) {
            if ([aPath hasSuffix:suffix]) {
                [self removeFile:aPath];
            }
        }
    }
}
  • 獲取文件大小
+(long long)getFileSize:(NSString*)path{
    unsigned long long fileLength = 0;
    NSNumber *fileSize;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSDictionary *fileAttributes = [fileManager attributesOfItemAtPath:path error:nil];
    if ((fileSize = [fileAttributes objectForKey:NSFileSize])) {
        fileLength = [fileSize unsignedLongLongValue]; //單位是 B
    }
    return fileLength;
}
  • 獲取文件的信息(包含了上面文件大小)
+(NSDictionary*)getFileInfo:(NSString*)path{
    NSError *error;
    NSDictionary *reslut =  [[NSFileManager defaultManager] attributesOfItemAtPath:path error:&error];
    if (error) {
        NSLog(@"getFileInfo Failed:%@",[error localizedDescription]);
    }
    return reslut;
}

[toc]

NSFileManager和NSFileHandle

1、NSFileManager(文件管理對象)

主要是對文件進(jìn)行的操作(創(chuàng)建/刪除/改名等)以及文件信息的獲取。

方法 說明
@property (class, readonly, strong) NSFileManager *defaultManager 創(chuàng)建文件管理對象
-(BOOL)fileExistsAtPath:(NSString *)path isDirectory:(nullable BOOL *)isDirectory 判斷某個(gè)路徑是否存在,isDirectory是一個(gè)指針,表示該路徑是否是目錄
-(BOOL)createDirectoryAtPath:(NSString *)path withIntermediateDirectories:(BOOL)createIntermediates attributes:(nullable NSDictionary<NSString *, id> *)attributes error:(NSError **)error 創(chuàng)建一個(gè)目錄
-(BOOL)createFileAtPath:(NSString *)path contents:(nullable NSData *)data attributes:(nullable NSDictionary<NSString *, id> *)attr 創(chuàng)建一個(gè)文件,可順便寫入data
-(BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile NSData類型的寫入數(shù)據(jù),讀數(shù)據(jù)請自行查閱
-(BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile encoding:(NSStringEncoding)enc error:(NSError **)error NSString、NSArray、NSDictionary的寫入數(shù)據(jù),讀數(shù)據(jù)請自行查閱
-(nullable NSArray<NSString *> *)contentsOfDirectoryAtPath:(NSString *)path error:(NSError **)error 獲取當(dāng)前文件夾下的文件/目錄
-(BOOL)moveItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error 移動(dòng)文件,可用來重命名
-(BOOL)copyItemAtURL:(NSURL *)srcURL toURL:(NSURL *)dstURL error:(NSError **)error 復(fù)制文件
-(BOOL)removeItemAtPath:(NSString *)path error:(NSError **)error 刪除文件
-(nullable NSDictionary<NSFileAttributeKey, id> *)attributesOfItemAtPath:(NSString *)path error:(NSError **)error 獲取文件信息(文件大小、修改時(shí)間、所有者等)

</b>

2、NSFileHandle(文件連接器)

主要是對文件內(nèi)容進(jìn)行讀取和寫入操作

方法 說明
+(nullable instancetype)fileHandleForWritingAtPath:(NSString *)path 寫的方式打開文件
+(nullable instancetype)fileHandleForReadingAtPath:(NSString *)path 讀的方式打開文件
-(unsigned long long)seekToEndOfFile 跳到文件末尾
-(void)seekToFileOffset:(unsigned long long)offset 跳到指定偏移位置
-(void)truncateFileAtOffset:(unsigned long long)offset 將文件的長度設(shè)為offset字節(jié)
-(NSData *)readDataToEndOfFile 從當(dāng)前字節(jié)讀取到文件到末尾數(shù)據(jù)
-(NSData *)readDataOfLength:(NSUInteger)length 從當(dāng)前字節(jié)讀取到指定長度數(shù)據(jù)
-(void)synchronizeFile 同步文件,通常用在寫入數(shù)據(jù)后
-(void)closeFile 關(guān)閉文件

[toc]

對象等復(fù)雜類型的讀寫操作

上述數(shù)據(jù)操作,支持的類型僅僅是NSString、NSArray、NSDictionary、NSData類型,這些都數(shù)據(jù)類型都支持了NSCoding協(xié)議,可以進(jìn)行數(shù)據(jù)持久化。如果我們想存儲(chǔ)如UIImage、自定義的對象等類型,我們都需要將其轉(zhuǎn)換為NSData類型,如轉(zhuǎn)換UIImage為NSData使用UIImagePNGRepresentation(image)等方法,而自定義對象類型則需要進(jìn)行歸檔、反歸檔來進(jìn)行存取操作

存:

對象->歸檔->NSData->文件寫入

取:

文件讀取->NSData->反歸檔->對象

自定義對象需要遵守NSCoding協(xié)議并實(shí)現(xiàn)

- (void)encodeWithCoder:(NSCoder *)aCoder;  //序列化 
- (id)initWithCoder:(NSCoder *)aDecoder;    //反序列化

兩個(gè)方法


[toc]

參考地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • *面試心聲:其實(shí)這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,217評論 30 472
  • 1、 沙盒概念基本介紹 iOS 應(yīng)用程序只能在該 app 的文件系統(tǒng)中讀取。這個(gè)默認(rèn)的 app 文件系統(tǒng)就是我們說...
    Laughingg閱讀 2,775評論 2 10
  • 目錄 沙盒及其結(jié)構(gòu) Preference(偏好設(shè)置)-Plist 屬性列表-Plist NSKeyedArchiv...
    Ryan___閱讀 543評論 0 0
  • 一、iOS中的沙盒機(jī)制 iOS應(yīng)用程序只能對自己創(chuàng)建的文件系統(tǒng)讀取文件,這個(gè)獨(dú)立、封閉、安全的空間,叫做沙盒。它一...
    1d5cb7cff98d閱讀 1,789評論 0 0
  • iOS開發(fā)-文件管理(一) 一、iOS中的沙盒機(jī)制 iOS應(yīng)用程序只能對自己創(chuàng)建的文件系統(tǒng)讀取文件,這個(gè)獨(dú)立、封閉...
    Friez平板支撐閱讀 4,644評論 0 1