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

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

沙盒機(jī)制

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

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

沙盒目錄

Documents

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

Library

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

tmp

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

如何查看該目錄?

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;
}
  • 移動文件
+(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 判斷某個路徑是否存在,isDirectory是一個指針淋淀,表示該路徑是否是目錄
-(BOOL)createDirectoryAtPath:(NSString *)path withIntermediateDirectories:(BOOL)createIntermediates attributes:(nullable NSDictionary<NSString *, id> *)attributes error:(NSError **)error 創(chuàng)建一個目錄
-(BOOL)createFileAtPath:(NSString *)path contents:(nullable NSData *)data attributes:(nullable NSDictionary<NSString *, id> *)attr 創(chuàng)建一個文件,可順便寫入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 移動文件炭臭,可用來重命名
-(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 獲取文件信息(文件大小、修改時間袍辞、所有者等)

</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ù)持久化。如果我們想存儲如UIImage详炬、自定義的對象等類型盐类,我們都需要將其轉(zhuǎn)換為NSData類型,如轉(zhuǎn)換UIImage為NSData使用UIImagePNGRepresentation(image)等方法呛谜,而自定義對象類型則需要進(jìn)行歸檔在跳、反歸檔來進(jìn)行存取操作

存:

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

取:

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

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

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

兩個方法


[toc]

參考地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末隐岛,一起剝皮案震驚了整個濱河市猫妙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌聚凹,老刑警劉巖割坠,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異妒牙,居然都是意外死亡彼哼,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門湘今,熙熙樓的掌柜王于貴愁眉苦臉地迎上來敢朱,“玉大人,你說我怎么就攤上這事摩瞎∷┣” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵旗们,是天一觀的道長蚓哩。 經(jīng)常有香客問我,道長上渴,這世上最難降的妖魔是什么岸梨? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮驰贷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘洛巢。我一直安慰自己括袒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布稿茉。 她就那樣靜靜地躺著锹锰,像睡著了一般芥炭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上恃慧,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天园蝠,我揣著相機(jī)與錄音,去河邊找鬼痢士。 笑死彪薛,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的怠蹂。 我是一名探鬼主播善延,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼城侧!你這毒婦竟也來了易遣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤嫌佑,失蹤者是張志新(化名)和其女友劉穎豆茫,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體屋摇,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡揩魂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了摊册。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肤京。...
    茶點(diǎn)故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖茅特,靈堂內(nèi)的尸體忽然破棺而出忘分,到底是詐尸還是另有隱情,我是刑警寧澤白修,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布妒峦,位于F島的核電站,受9級特大地震影響兵睛,放射性物質(zhì)發(fā)生泄漏肯骇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一祖很、第九天 我趴在偏房一處隱蔽的房頂上張望笛丙。 院中可真熱鬧,春花似錦假颇、人聲如沸胚鸯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽姜钳。三九已至坦冠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間哥桥,已是汗流浹背辙浑。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拟糕,地道東北人判呕。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像已卸,于是被迫代替她去往敵國和親佛玄。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評論 2 345

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

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