iOS進階(一)數(shù)據(jù)處理之文件讀寫

一、沙盒機制

沙盒機制

  • 每一個應用程序都會擁有一個應用程序沙盒
  • 應用程序沙盒就是一個文件系統(tǒng)目錄

iOS中的沙盒機制

  • 沙盒是一種安全體系
  • TA規(guī)定了應用程序只能在為該程序創(chuàng)建的文件夾(沙盒)內(nèi)訪問文件,不可以訪問其他沙盒內(nèi)的內(nèi)容(iOS8已經(jīng)部分開放訪問)
  • 所有的非代碼文件都保存在這個地方,比如圖片、音樂、屬性列表(plist)、sqlite數(shù)據(jù)庫和文本文件等

沙盒機制的特點

  • 每個應用程序的活動范圍都限定在自己的沙盒里面
  • 不能隨意跨越自己的沙盒去訪問別的應用程序沙盒中的內(nèi)容(iOS已經(jīng)部分開放訪問)
  • 應用程序向外請求或接受數(shù)據(jù)都需要經(jīng)過權(quán)限認證

前往沙盒路徑方法

  • 選中要前往的路徑,右鍵
  • 選中Services選項
  • 點擊Reveal in Finder


    前往沙盒路徑.png

沙盒中的文件夾

  • Documents:保存應用運行時生成的需要持久化的數(shù)據(jù),iTunes會自動備份該目錄
  • Library:存儲程序的默認設置和其他狀態(tài)信息,iTunes會自動備份該目錄。
  • Library/Caches:存放緩存文件,iTunes不會備份此目錄,次目錄下文件不會在應用退出刪除。
  • Library/Preferences:保存應用的所有偏好設置,iOS的Settings(設置)應用會在該目錄中查找應用的設置信息,iTunes會自動備份該目錄。注意:你不會直接創(chuàng)建偏好設置文件,二十應該使用NSUserDefaults類來獲得和設置應用程序的偏好
  • tmp:保存應用運行時所需的臨時數(shù)據(jù),使用完畢后再將相應的文件從該目錄刪除。應用沒有運行時,系統(tǒng)也有可能會清楚該目錄下的文件,iTunes不會同步該目錄。iphone重啟時,該目錄下的文件會被刪除

獲取Documents目錄

 NSString *path = [[NSString NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];

獲取tmp目錄

NSString *tmpPath  = NSTemporaryDirectory();

獲取Library目錄

NSString *libPath = [[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) firstObject];

獲取Library/Caches目錄

NSString *cachePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask, YES) firstObject];

獲取Library/Preferences目錄

NSString *libPath = [[NSSeachForPathDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) firstObject];
NSString *prePath = [libPath stringByAppendingPathComponent:@"Preferences"];

應用程序包所在位置

NSString *path = [NSBundle mainBundle].resourcePth;

二、簡單對象的讀寫(I/O)操作

iOS中提供4種類型可以直接進行文件存取
NSString、NSArray、NSDictionary、NSData


以上類型包含子類

字符串寫入沙盒

// 在Documents下面創(chuàng)建一個文本路徑,假設文本名稱為bada.txt
NSString *txtPath = [docPath stringByAppendingPathComponent:@"bada.txt"];// 此時僅存在路徑,文件并沒有真實存在
NSString *string = @"中二洪荒巴達之力";
[string writeToFile:txtPath atomically:YES encoding:NSUTF8StringEncoding error:nil];// 字符串寫入時執(zhí)行的代碼
NSLog(@"%@", txtPath);

從文件中讀取字符串的方法

NSString *resultString = [NSString stringWithContentsOfFile:txtPath encoding:NSUTF8StringEncoding error:nil];
NSLog(@"%@", resultString);

數(shù)組寫入文件

// 創(chuàng)建一個存儲數(shù)組的文件路徑
NSString *filePath = [docPath stringByAppendingPathComponent:@"girl.txt"];
NSArray *arr = @[@"媽", @"的", @"智", @"障"];
[arr writeToFile:filePath atomically:YES];
NSLog(@"%@", filePath);

從文件中讀取數(shù)組的方法

NSArray *resultArr = [NSArray arrayWithContentsOfFile:filePath];
NSLog(@"%@", resultArr);

字典寫入文件

NSString *dicPath = [docPath stringByAppendingString:@"dic.txt"];
NSDictionary *dic = @{@"你" : @"智障", @"我" : @"機智"};
[dic writeToFile:dicPath atomically:YES];
NSLog(@"%@", dicPath);

從文件中讀取字典

NSDictionary *resultDic = [NSDictionary dictionaryWithContentsOfFile:dicPath];
NSLog(@"%@", resultDic);

NSData寫入文件

NSString *dataPath = [docPath stringByAppendingPathComponent:@"icon"];
// 得到一個UIImage對象
UIImage *image = [UIImage imageNamed:@"icon.jpg"];
// 將UIImage對象轉(zhuǎn)換成NSData對象
NSData *data = UIImageJPEGRepresentation(image, 1.0);
[data writeToFile:dataPath atomically:YES];
NSLog(@"%@", dataPath);

從文件中讀取NSData文件

NSData *resultData = [NSData dataWithContentsOfFile:dataPath];
// 將得到的NSData數(shù)據(jù)轉(zhuǎn)換為原有的圖片對象
UIImage *resultImage = [UIImage imageWithData:resultData];
// 顯示圖片
UIImageView *imageView = [[UIImageView alloc ] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
imageView.image = resultImage;
[self.view addSubview:imageView];

以上的運行結(jié)果都可以從沙盒路徑中的文件夾中看到

三、文件管理器與文件對接器

  • 文件管理器(NSFileManager):此類主要是對文件進行的操作(創(chuàng)建/從刪除/改名等)以及文件信息的獲取
  • 文件連接器(NSFileHandle):此類主要是對內(nèi)容進行讀取和寫入操作

文件管理器的使用

創(chuàng)建文件夾

- (IBAction)createDirectory:(UIButton *)sender
{
    // 1.找到Caches的路徑
    NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
    // 2.獲取創(chuàng)建的文件夾的路徑
    NSString *directoryPath = [cachePath stringByAppendingPathComponent:@"downloadImages"];
    // 3.創(chuàng)建文件夾需要一個文件管理對象(單例)
    NSFileManager *fileManager = [NSFileManager defaultManager];
    // 4.創(chuàng)建文件夾
    [fileManager createDirectoryAtPath:directoryPath withIntermediateDirectories:YES attributes:nil error:nil];
    
    NSLog(@"%@", directoryPath);
}

創(chuàng)建文件以及獲取文件信息

- (IBAction)createFile:(UIButton *)sender
{
    // 1.得到Documents的路徑
    NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    // 2.創(chuàng)建一個文件路徑
    NSString *filePath = [docPath stringByAppendingPathComponent:@"qiuxiang.txt"];
    // 3.創(chuàng)建文件首先需要一個文件管理對象
    NSFileManager *fileManager = [NSFileManager defaultManager];
    // 4.創(chuàng)建文件
    [fileManager createFileAtPath:filePath contents:[@"badaas;ldkjf;alskdjf;akjdsf;lakjsdflakjsd;flkajsdlfkjasdlfkjasldfkja;lsdfkjasldkjf;asldkfj;asfjas;ldkfjasldkfjasldkfja;lsdkfjasl;dkjfs;ladkfja;sdkfjalsdkfjalsdfkja;sdfkja;dfkja;slfkdjsalkfja;slfkja;slkdfj" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil];
    
    NSLog(@"%@", filePath);
    
    // 獲取默認文件或者某個文件夾的大小
    NSDictionary *dic = [fileManager attributesOfItemAtPath:filePath error:nil];
    NSLog(@"%@", dic);
    NSNumber *number = [dic objectForKey:NSFileSize];
    NSLog(@"%@", number);
}

文件移動

/**
    在Documents文件夾下,創(chuàng)建一個文件夾(path),在該文件夾下創(chuàng)建一個文件(test.txt),將一個圖片對象存入到該文件中,然后在Caches文件夾下創(chuàng)建一個文件夾名為"testDirectroy",將test.txt文件移動到這個文件夾下.
 */


// 創(chuàng)建文件夾
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSString *dirPath = [docPath stringByAppendingPathComponent:@"path"];
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager createDirectoryAtPath:dirPath withIntermediateDirectories:YES attributes:nil error:nil];

// 創(chuàng)建文件
NSString *filePath = [dirPath stringByAppendingPathComponent:@"test.txt"];
[fileManager createFileAtPath:filePath contents:nil attributes:nil];

// 將圖片對象存入到該文件中
UIImage *image = [UIImage imageNamed:@"icon.jpg"];
NSData *data = UIImageJPEGRepresentation(image, 1.0);
[data writeToFile:filePath atomically:YES];
NSLog(@"%@", filePath);

// 移動文件
NSString *desPath = [docPath stringByAppendingPathComponent:@"test.txt"];
[fileManager moveItemAtPath:filePath toPath:desPath error:nil];

文件對接器的使用

/**
     練習要求:從一個文件中指定的位置開始追加內(nèi)容
     提示:
     1、在documents目錄下創(chuàng)建一個test.txt文件,文件中的內(nèi)容為"abcdefg"
     2、從文件偏移量為3那個位置開始追加內(nèi)容"1234"
 */

- (void)change
{
    // 1.獲取Documents路徑
    NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    // 2.創(chuàng)建文件路徑
    NSString *filePath = [docPath stringByAppendingPathComponent:@"text.txt"];
    // 3.使用文件管理對象創(chuàng)建文件
    NSFileManager *fileManager = [NSFileManager defaultManager];
    [fileManager createFileAtPath:filePath contents:[@"abcdefg" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil];
    // 4.創(chuàng)建文件對接對象
    NSFileHandle *handle = [NSFileHandle fileHandleForUpdatingAtPath:filePath];// 文件對象此時針對文件,可讀可寫
    // 5.將偏移量移動到3的位置
    [handle seekToFileOffset:3];
    // 6.寫入數(shù)據(jù)
    [handle writeData:[@"1234" dataUsingEncoding:NSUTF8StringEncoding]];
    // 7.執(zhí)行完操作后,關(guān)閉文件
    [handle closeFile];
    
    NSLog(@"%@", filePath);
}

PS:這個題目有點坑爹,說是追加,其實是把defg替換成1234.

四、復雜對象的讀寫(I/O)操作

復雜對象:在Foundation框架內(nèi)不存在的數(shù)據(jù)類,如自定義的Person類無法在程序內(nèi)通過writeToFile:這個方法寫入到文件內(nèi)

  • 如何將復雜對象寫入文件
  • 歸檔:只能通過將復雜對象轉(zhuǎn)換為NSData,然后寫入文件。
  • 如何從文件中讀取復雜對象
  • 反歸檔(又稱解檔):將NSData轉(zhuǎn)換為復雜對象

①.復雜對象寫入文件的過程:復雜對象->歸檔->NSData->writeToFile
②.從文件中讀取出復雜對象過程:讀取文件->NSData->反歸檔->復雜對象

歸檔與反歸檔

首先,復雜對象所屬的類要遵守<NSCoding>協(xié)議

@interface Person : NSObject <NSCoding>

@property (copy, nonatomic) NSString *name;
@property (copy, nonatomic) NSString *age;
@property (copy, nonatomic) NSString *gender;

- (instancetype)initWithName:(NSString *)name age:(NSString *)age gender:(NSString *)gender;

@end

然后實現(xiàn)其中的兩個方法

// NSCoder是iOS中的編碼解碼類
// 歸檔時調(diào)用
- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeObject:self.age forKey:@"age"];
    [aCoder encodeObject:self.gender forKey:@"gender"];
}

// 解檔時調(diào)用
- (id)initWithCoder:(NSCoder *)aDecoder
{
    NSString *name = [aDecoder decodeObjectForKey:@"name"];
    NSString *age = [aDecoder decodeObjectForKey:@"age"];
    NSString *gender = [aDecoder decodeObjectForKey:@"gender"];
    return [self initWithName:name age:age gender:gender];
}

進行歸檔或者反歸檔

// 歸檔
- (IBAction)archiver:(id)sender {
    // 創(chuàng)建兩個人
    Person *bada = [[Person alloc] initWithName:@"bada" age:@"18" gender:@"男"];
    Person *qiuxiang = [[Person alloc] initWithName:@"qiuxiang" age:@"18" gender:@"女"];
    
    // 獲取到Documents路徑
    NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    
    // iOS中的歸檔類是NSKeyeArchiver,作用是:將復雜對象轉(zhuǎn)換為NSData對象
    // 創(chuàng)建一個可變數(shù)據(jù)對象
    NSMutableData *mData = [NSMutableData data];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:mData];
    // 歸檔時要給歸檔對象添加標記
    [archiver encodeObject:bada forKey:@"bada"];
    [archiver encodeObject:qiuxiang forKey:@"qiuxiang"];
    // 結(jié)束歸檔,不管還有多少未歸檔的對象,都不會執(zhí)行歸檔操作
    [archiver finishEncoding];
    
    // 將數(shù)據(jù)寫入文件
    // 創(chuàng)建文件路徑
    NSString *filePath = [docPath stringByAppendingPathComponent:@"bada.qiuxiang"];
    [mData writeToFile:filePath atomically:YES];
    
    NSLog(@"歸檔");
}

// 反歸檔
- (IBAction)unarchiver:(id)sender {
    // 獲取存放數(shù)據(jù)的路徑
    NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    NSString *filePath = [docPath stringByAppendingPathComponent:@"bada.qiuxiang"];
    // 從路徑中獲取NSData對象
    NSData *data = [NSData dataWithContentsOfFile:filePath];
    
    // iOS中的解檔類是NSKeyedUnarchiver,作用是:將NSData對象還原成原本的復雜對象
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
    
    // 解檔
    Person *bada = [unarchiver decodeObjectForKey:@"bada"];
    NSLog(@"name is %@, age is %@, gender is %@ 解檔成功", bada.name, bada.age, bada.gender);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

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