iOS 沙盒&NSFileManager&歸檔

創(chuàng)建文件夾、創(chuàng)建文件、文件夾里面創(chuàng)建文件

一.幾種沙盒常用的存儲(chǔ)方式

1. 項(xiàng)目中常用的NSUserDefaults存放的地址是:Library/Preferences,里面以bundleId為名的偏好設(shè)置plist文件里面;
   Library/Preferences包含應(yīng)用程序的偏好設(shè)置文件,您不應(yīng)該直接創(chuàng)建偏好設(shè)置文件,而是應(yīng)該使用NSUserDefaults類來取得和設(shè)置應(yīng)用程序的偏好。
2. 在使用plist進(jìn)行數(shù)據(jù)存儲(chǔ)和讀取,只適用于系統(tǒng)自帶的一些常用類型才能用,且必須先獲取路徑相對(duì)麻煩;
3. 歸檔:因?yàn)殚g接(NSUserDefaults)或者直接操作使用plist文件,只能存儲(chǔ)常用的類型, 而歸檔可以實(shí)現(xiàn)把自定義的對(duì)象存放在文件中。

二. 存取的方式
通常用fileManager寫入的例如頁面信息等大量緩存等存放地址是:Library/Caches; 寫入的運(yùn)行過程產(chǎn)生的如用戶信息等需要持久化的數(shù)據(jù),可以寫入document。
NSUserDefaults直接寫入后,是默認(rèn)存放在系統(tǒng)偏好設(shè)置的plist文件(registerDefaults方法除外,它沒有寫入plist)。

fileManager寫入:

1. 先創(chuàng)建路徑(也就文件夾路徑):
        NSFileManager *fileM = [NSFileManager defaultManager];
        NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject stringByAppendingPathComponent:@"wgj01"];
        if (![fileM fileExistsAtPath:documentsPath]) { 
            [fileM createDirectoryAtPath:documentsPath withIntermediateDirectories:YES attributes:nil error:nil];
        }

2. 寫入方式一:
        NSString *filePath = [documentsPath stringByAppendingPathComponent:@"w"];
        NSDictionary *dict = @{@"w":@"wwww"};
        [dict writeToFile:filePath atomically:YES];
這樣寫入之后,在NSCachesDirectory里面的wgj01文件夾中有一個(gè)w文件,因?yàn)闆]有后綴,所以存放格式為xml格式。

3. 寫入方式二:
        NSString *filePath = [documentsPath stringByAppendingPathComponent:@"ws.plist"];
        NSDictionary *dict = @{@"w":@"wwww"};
        [dict writeToFile:filePath atomically:YES];
文件ws有后綴,寫入的是plist格式。

3.1 針對(duì)3 的讀取&修改方式:
     //讀?。?      NSString *filePath = [documentsPath   stringByAppendingPathComponent:@"ws.plist"];
      NSMutableDictionary *dataDict = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
         NSLog(@"\n\n\n%@",dataDict);
     //修改或添加:
        [dataDict setObject:@"mmmmm" forKey:@"m"];
        [dataDict writeToFile:filePath atomically:YES];

3.2   對(duì)于項(xiàng)目文件中的plist文件:
      NSString *filePath = [[NSBundle mainBundle] pathForResource:@"wgjTT" ofType:@"plist"];
     和沙盒里面的plist文件(上面3.1)一樣,對(duì)解析出來的字典或者數(shù)組進(jìn)行增刪改等操作,
但是,操作后,點(diǎn)擊查看plist文件,發(fā)現(xiàn)沒有變化,而,打印:
        NSMutableDictionary *dataDictafter = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath1];
        NSLog(@"\n\n\nTT0:\ndataDictafter:\n%@",dataDictafter);
發(fā)現(xiàn),打印結(jié)果時(shí)改變后的結(jié)果。

猜測(cè):應(yīng)該是只寫入了緩存,等程序重新運(yùn)行,打印plist數(shù)據(jù)結(jié)果還是修改前的結(jié)果(plist并未有實(shí)質(zhì)性的改變)。

4. 寫入方式三:
        NSString *filePath = [documentsPath stringByAppendingPathComponent:@"wh"];
        NSDictionary *dict = @{@"w":@"wwww"};
        NSData *data = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:nil];
        [fileM createFileAtPath:filePath contents:data attributes:nil];
這樣,在wgj01文件夾下有一個(gè)wh文件,它里面的格式為:json格式。
eg.
{
  "w" : "wwww"
}

4.1 針對(duì)4的讀出方式:
NSString *filePath = [documentsPath stringByAppendingPathComponent:@"wh"];
 NSData *data =  [NSData dataWithContentsOfFile:filePath];
 NSDictionary *object11 = [NSJSONSerialization JSONObjectWithData:data options:(NSJSONReadingMutableContainers) error:nil];
        NSLog(@"\n\n\n%@",object11); //讀取成功

5. 若想要繼續(xù)創(chuàng)建文件夾,用stringByAppendingPathComponent后面拼接文件夾名稱 并且 用        if (![fileM fileExistsAtPath:documentsPath]) {
            [fileM createDirectoryAtPath:documentsPath withIntermediateDirectories:YES attributes:nil error:nil];
        }創(chuàng)建文件夾。

沙盒路徑各目錄用途:

Documents 目錄:您應(yīng)該將所有de應(yīng)用程序數(shù)據(jù)文件寫入到這個(gè)目錄下。這個(gè)目錄用于存儲(chǔ)用戶數(shù)據(jù)或其它應(yīng)該定期備份的信息。

AppName.app 目錄:這是應(yīng)用程序的程序包目錄,包含應(yīng)用程序的本身。由于應(yīng)用程序必須經(jīng)過簽名,所以您在運(yùn)行時(shí)不能對(duì)這個(gè)目錄中的內(nèi)容進(jìn)行修改,否則可能會(huì)使應(yīng)用程序無法啟動(dòng)。

Library 目錄:這個(gè)目錄下有兩個(gè)子目錄:Caches 和 Preferences

Library/Preferences 目錄:包含應(yīng)用程序的偏好設(shè)置文件。您不應(yīng)該直接創(chuàng)建偏好設(shè)置文件,而是應(yīng)該使用NSUserDefaults類來取得和設(shè)置應(yīng)用程序的偏好.

Library/Caches 目錄:用于存放應(yīng)用程序?qū)S玫闹С治募?,保存?yīng)用程序再次啟動(dòng)過程中需要的信息。

tmp 目錄:這個(gè)目錄用于存放臨時(shí)文件,保存應(yīng)用程序再次啟動(dòng)過程中不需要的信息。

1  應(yīng)用程序包:包含所有資源文件和可執(zhí)行文件  
2  Documents:保存應(yīng)用運(yùn)行時(shí)生成的需要持久化的數(shù)據(jù),iTunes會(huì)自動(dòng)備份該目錄  
3  tmp:保存應(yīng)用運(yùn)行時(shí)所需的臨時(shí)數(shù)據(jù),使用完畢后再將相應(yīng)的文件從該目錄刪除,應(yīng)用沒有運(yùn)行時(shí),系統(tǒng)也可能會(huì)自動(dòng)清理該目錄下的文件,iTunes不會(huì)同步該目錄,iPhone重啟時(shí)該目錄下的文件會(huì)丟失。
4  Libaray:存儲(chǔ)程序的默認(rèn)設(shè)置和其他狀態(tài)信息,iTunes會(huì)自動(dòng)備份該目錄。  
5  Libaray/Caches:存放緩存文件,iTunes不會(huì)備份此目錄,此目錄下文件不會(huì)在應(yīng)用退出刪除,一般存放體積比較大,不是很重要的資源  
6  Libaray/Preferences:保存應(yīng)用的所有偏好設(shè)置,ios的Settings(設(shè)置)應(yīng)用會(huì)在該目錄中查找應(yīng)用的設(shè)置信息,iTunes會(huì)自動(dòng)備份該目錄。

沙盒路徑地址的獲?。?/p>

1,獲取家目錄路徑的函數(shù):  
NSString *homeDir = NSHomeDirectory();  
2,獲取Documents目錄路徑的方法:  
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);  
NSString *docDir = [paths objectAtIndex:0];  
3,獲取Caches目錄路徑的方法:  
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);  
NSString *cachesDir = [paths objectAtIndex:0];  
4,獲取tmp目錄路徑的方法:  
NSString *tmpDir = NSTemporaryDirectory();  
5,獲取應(yīng)用程序程序包中資源文件路徑的方法:  
例如獲取程序包中一個(gè)圖片資源(apple.png)路徑的方法:  
NSString *imagePath = [[NSBundle mainBundle] pathForResource:@”apple” ofType:@”png”];  
UIImage *appleImage = [[UIImage alloc] initWithContentsOfFile:imagePath];  
代碼中的mainBundle類方法用于返回一個(gè)代表應(yīng)用程序包的對(duì)象。

e.g.

NSString *Path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    NSLog(@"目錄:%@",Path);
    
    NSString *dataStr1 = @"testdata";
    NSString *dataStr2 = @"wgjwgj";
    NSString *dataStr3 = @"umeng";
    
    NSData *data1 = [dataStr1 dataUsingEncoding:NSUTF8StringEncoding];
    NSData *data2 = [dataStr2 dataUsingEncoding:NSUTF8StringEncoding];
    NSData *data3 = [dataStr3 dataUsingEncoding:NSUTF8StringEncoding];
    
    NSString *path1 = [Path stringByAppendingPathComponent:@"wgjTest1"];
    NSString *path2 = [Path stringByAppendingPathComponent:@"wgjTest2"];
    
    NSString *path4 = [Path stringByAppendingPathComponent:@"wgjjm"];
    
    NSFileManager *fileManager1 = [NSFileManager defaultManager];
    //創(chuàng)建文件夾
    [fileManager1 createDirectoryAtPath:path4 withIntermediateDirectories:YES attributes:nil error:nil];
    //創(chuàng)建文件
    [fileManager1 createFileAtPath:path1 contents:data1 attributes:nil];
    [fileManager1 createFileAtPath:path2 contents:data2 attributes:nil];
    //文件夾里面創(chuàng)建文件
    NSString *path5 = [path4 stringByAppendingPathComponent:@"wgj5"];
    [fileManager1 createFileAtPath:path5 contents:data3 attributes:nil];
    
    NSURL *url = [NSURL fileURLWithPath:Path isDirectory:YES];
    //遍歷url這個(gè)相應(yīng)的目錄下的文件和文件夾以及文件夾中的文件,得出文件夾/文件目錄,和文件大小
    NSDirectoryEnumerator *fileEnumerator = [fileManager1 enumeratorAtURL:url
                                               includingPropertiesForKeys:@[NSFileSize]
                                                                  options:NSDirectoryEnumerationSkipsHiddenFiles
                                                             errorHandler:NULL];
    NSUInteger fileCount = 0;
    NSUInteger totalSize = 0;
    for (NSURL *fileURL in fileEnumerator) {
        NSNumber *fileSize;
        [fileURL getResourceValue:&fileSize forKey:NSURLFileSizeKey error:NULL];
        totalSize += fileSize.unsignedIntegerValue;
        fileCount += 1;
    }

YYModel的yy_modelEncodeWithCoder和yy_modelInitWithCoder
1. 當(dāng)自己實(shí)現(xiàn)歸檔archive的時(shí)候,需要實(shí)現(xiàn)<NSCoding>協(xié)議encode和code方法,并且需要把類里面的所有屬性在encode和code方法中全部羅列操作一遍,很是麻煩,所以就可以使用YYModel的歸檔;
2. YYModel實(shí)現(xiàn)歸檔主要點(diǎn):
    a. 把屬性分為幾種類型,它把int bool等數(shù)值類型都轉(zhuǎn)為了NSNumber類型并使用encodeObject:forKey: 直接當(dāng)成object處理。
    b. 把類對(duì)象的結(jié)構(gòu)直接映射拿了出來,并映射到Y(jié)Y自己自定義的結(jié)構(gòu),之后循環(huán)判斷此類和父類一直向上找,取出所有的屬性并操作賦值。此取出屬性,包括了類所有父類的自定義屬性。
    c. 通過objc_property_attribute_t獲取成員變量的類型,并通過字符判斷具體類型返回類型枚舉以供使用。

MJModel的mj_decode和mj_encode
1. 其實(shí)mj的encode原理和YY的差不多,只不過,mj只是利用的objc_property_t的runtime方法,沒有自定義和系統(tǒng)類相似的結(jié)構(gòu)做映射;也是循環(huán)類的諸多父類,找出所有的自定義屬性。
2. 因?yàn)闆]有做結(jié)構(gòu)體的映射,所以表面看起來稍微簡(jiǎn)單些。
3. 在encode的時(shí)候,也是把數(shù)值布爾等類型轉(zhuǎn)化為NSNumber類型,進(jìn)行encodeObject;具體做法是根據(jù)方法property_getAttributes,獲取類型字符串然后截取,如果是q或者i等等數(shù)值類型,就歸為NSNumber。

NSKeyedArchiver
  1. 對(duì)單個(gè)對(duì)象歸檔解擋
方式a.    歸: NSData *arData = [NSKeyedArchiver archivedDataWithRootObject:model1];
    [arData writeToFile:path1 atomically:YES];
    解:    NSData *resultData = [NSData dataWithContentsOfFile:path1];
    id result = [NSKeyedUnarchiver unarchiveObjectWithData:resultData];
方式b. 歸:BOOL isSuccess = [NSKeyedArchiver archiveRootObject:model1 toFile:path1];
    解:id result = [NSKeyedUnarchiver unarchiveObjectWithFile:path1];

  1. 對(duì)多個(gè)對(duì)象歸檔解擋
1.  歸:   NSMutableData *data = [NSMutableData data];
    NSKeyedArchiver *archive1 = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
    [archive1 encodeObject:@"13223432342" forKey:@"111"];
    [archive1 encodeObject:model forKey:@"222"];
    [archive1 finishEncoding];
    BOOL is1 = [data writeToFile:path1 atomically:YES];
解:    NSData *data2 = [NSData dataWithContentsOfFile:path1];
    NSKeyedUnarchiver *archive2 = [[NSKeyedUnarchiver alloc] initForReadingWithData:data2];
    id result21 = [archive2 decodeObjectForKey:@"111"];
    id result22 = [archive2 decodeObjectForKey:@"222"];
    NSLog(@"resut21:%@\n result22:%@",result21,result22);

注意:多個(gè)對(duì)象initForWritingWithMutableData歸檔時(shí),finishEncoding方法之后,不能在歸檔,再寫encode會(huì)報(bào)錯(cuò);所以這個(gè)和數(shù)據(jù)庫不一樣,也就不能在多個(gè)地方寫入,只能一次性寫入,如多次針對(duì)同路徑文件寫入,需要?jiǎng)?chuàng)建多次keyArchive,原來的文件內(nèi)容會(huì)被清掉,只保存最近的寫入內(nèi)容。
單個(gè)對(duì)象歸檔也是一樣,是直接清掉之前并寫入新的信息。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容