一、沙盒機制
沙盒機制
- 每一個應用程序都會擁有一個應用程序沙盒
- 應用程序沙盒就是一個文件系統目錄
iOS中的沙盒機制
- 沙盒是一種安全體系
- TA規定了應用程序只能在為該程序創建的文件夾(沙盒)內訪問文件,不可以訪問其他沙盒內的內容(iOS8已經部分開放訪問)
- 所有的非代碼文件都保存在這個地方,比如圖片、音樂、屬性列表(plist)、sqlite數據庫和文本文件等
沙盒機制的特點
- 每個應用程序的活動范圍都限定在自己的沙盒里面
- 不能隨意跨越自己的沙盒去訪問別的應用程序沙盒中的內容(iOS已經部分開放訪問)
- 應用程序向外請求或接受數據都需要經過權限認證
前往沙盒路徑方法
- 選中要前往的路徑,右鍵
- 選中Services選項
-
點擊Reveal in Finder
前往沙盒路徑.png
沙盒中的文件夾
- Documents:保存應用運行時生成的需要持久化的數據,iTunes會自動備份該目錄
- Library:存儲程序的默認設置和其他狀態信息,iTunes會自動備份該目錄。
- Library/Caches:存放緩存文件,iTunes不會備份此目錄,次目錄下文件不會在應用退出刪除。
- Library/Preferences:保存應用的所有偏好設置,iOS的Settings(設置)應用會在該目錄中查找應用的設置信息,iTunes會自動備份該目錄。注意:你不會直接創建偏好設置文件,二十應該使用NSUserDefaults類來獲得和設置應用程序的偏好
- tmp:保存應用運行時所需的臨時數據,使用完畢后再將相應的文件從該目錄刪除。應用沒有運行時,系統也有可能會清楚該目錄下的文件,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下面創建一個文本路徑,假設文本名稱為bada.txt
NSString *txtPath = [docPath stringByAppendingPathComponent:@"bada.txt"];// 此時僅存在路徑,文件并沒有真實存在
NSString *string = @"中二洪荒巴達之力";
[string writeToFile:txtPath atomically:YES encoding:NSUTF8StringEncoding error:nil];// 字符串寫入時執行的代碼
NSLog(@"%@", txtPath);
從文件中讀取字符串的方法
NSString *resultString = [NSString stringWithContentsOfFile:txtPath encoding:NSUTF8StringEncoding error:nil];
NSLog(@"%@", resultString);
數組寫入文件
// 創建一個存儲數組的文件路徑
NSString *filePath = [docPath stringByAppendingPathComponent:@"girl.txt"];
NSArray *arr = @[@"媽", @"的", @"智", @"障"];
[arr writeToFile:filePath atomically:YES];
NSLog(@"%@", filePath);
從文件中讀取數組的方法
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對象轉換成NSData對象
NSData *data = UIImageJPEGRepresentation(image, 1.0);
[data writeToFile:dataPath atomically:YES];
NSLog(@"%@", dataPath);
從文件中讀取NSData文件
NSData *resultData = [NSData dataWithContentsOfFile:dataPath];
// 將得到的NSData數據轉換為原有的圖片對象
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];
以上的運行結果都可以從沙盒路徑中的文件夾中看到
三、文件管理器與文件對接器
- 文件管理器(NSFileManager):此類主要是對文件進行的操作(創建/從刪除/改名等)以及文件信息的獲取
- 文件連接器(NSFileHandle):此類主要是對內容進行讀取和寫入操作
文件管理器的使用
創建文件夾
- (IBAction)createDirectory:(UIButton *)sender
{
// 1.找到Caches的路徑
NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
// 2.獲取創建的文件夾的路徑
NSString *directoryPath = [cachePath stringByAppendingPathComponent:@"downloadImages"];
// 3.創建文件夾需要一個文件管理對象(單例)
NSFileManager *fileManager = [NSFileManager defaultManager];
// 4.創建文件夾
[fileManager createDirectoryAtPath:directoryPath withIntermediateDirectories:YES attributes:nil error:nil];
NSLog(@"%@", directoryPath);
}
創建文件以及獲取文件信息
- (IBAction)createFile:(UIButton *)sender
{
// 1.得到Documents的路徑
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
// 2.創建一個文件路徑
NSString *filePath = [docPath stringByAppendingPathComponent:@"qiuxiang.txt"];
// 3.創建文件首先需要一個文件管理對象
NSFileManager *fileManager = [NSFileManager defaultManager];
// 4.創建文件
[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文件夾下,創建一個文件夾(path),在該文件夾下創建一個文件(test.txt),將一個圖片對象存入到該文件中,然后在Caches文件夾下創建一個文件夾名為"testDirectroy",將test.txt文件移動到這個文件夾下.
*/
// 創建文件夾
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];
// 創建文件
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];
文件對接器的使用
/**
練習要求:從一個文件中指定的位置開始追加內容
提示:
1、在documents目錄下創建一個test.txt文件,文件中的內容為"abcdefg"
2、從文件偏移量為3那個位置開始追加內容"1234"
*/
- (void)change
{
// 1.獲取Documents路徑
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
// 2.創建文件路徑
NSString *filePath = [docPath stringByAppendingPathComponent:@"text.txt"];
// 3.使用文件管理對象創建文件
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager createFileAtPath:filePath contents:[@"abcdefg" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil];
// 4.創建文件對接對象
NSFileHandle *handle = [NSFileHandle fileHandleForUpdatingAtPath:filePath];// 文件對象此時針對文件,可讀可寫
// 5.將偏移量移動到3的位置
[handle seekToFileOffset:3];
// 6.寫入數據
[handle writeData:[@"1234" dataUsingEncoding:NSUTF8StringEncoding]];
// 7.執行完操作后,關閉文件
[handle closeFile];
NSLog(@"%@", filePath);
}
PS:這個題目有點坑爹,說是追加,其實是把defg替換成1234.
四、復雜對象的讀寫(I/O)操作
復雜對象:在Foundation框架內不存在的數據類,如自定義的Person類無法在程序內通過writeToFile:這個方法寫入到文件內
- 如何將復雜對象寫入文件
- 歸檔:只能通過將復雜對象轉換為NSData,然后寫入文件。
- 如何從文件中讀取復雜對象
- 反歸檔(又稱解檔):將NSData轉換為復雜對象
①.復雜對象寫入文件的過程:復雜對象->歸檔->NSData->writeToFile
②.從文件中讀取出復雜對象過程:讀取文件->NSData->反歸檔->復雜對象
歸檔與反歸檔
首先,復雜對象所屬的類要遵守<NSCoding>協議
@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
然后實現其中的兩個方法
// NSCoder是iOS中的編碼解碼類
// 歸檔時調用
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeObject:self.age forKey:@"age"];
[aCoder encodeObject:self.gender forKey:@"gender"];
}
// 解檔時調用
- (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 {
// 創建兩個人
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,作用是:將復雜對象轉換為NSData對象
// 創建一個可變數據對象
NSMutableData *mData = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:mData];
// 歸檔時要給歸檔對象添加標記
[archiver encodeObject:bada forKey:@"bada"];
[archiver encodeObject:qiuxiang forKey:@"qiuxiang"];
// 結束歸檔,不管還有多少未歸檔的對象,都不會執行歸檔操作
[archiver finishEncoding];
// 將數據寫入文件
// 創建文件路徑
NSString *filePath = [docPath stringByAppendingPathComponent:@"bada.qiuxiang"];
[mData writeToFile:filePath atomically:YES];
NSLog(@"歸檔");
}
// 反歸檔
- (IBAction)unarchiver:(id)sender {
// 獲取存放數據的路徑
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);
}