一、沙盒機制
1.什麼是沙盒
通俗的說,就是将一個應用程式的所有的非代碼檔案放在一個檔案夾裡(沙盒),應用程式隻能從該檔案系統讀取檔案,不能去其他地方通路。
每一個iOS應用程式都會為自己建立一個檔案系統目錄。這個獨立封閉、安全的空間,叫做沙盒。
2.打開模拟器的沙盒目錄
點選finder----點選菜單欄的前往----按住alt,出現了隐藏的資源庫選項----點選資源庫----developer----CoreSimulator----Devices,然後發現這裡有很多的一長串字母的檔案,
根據時間找到最新的一個檔案打開。
或者在終端寫 : defaults write com.apple.finder AppleShowAllFiles -bool true ,也可以顯示隐藏檔案
看到裡面有三個并列檔案夾 Library,Documents,tmp
Document:
隻有使用者生成的檔案、其他資料及其他程式不能重新建立的檔案,應該儲存在<Application_Home>/Documents 目錄下面,并将通過iCloud自動備份,應該将所有的應用程式資料檔案寫入到這個目錄下。
Library:iTunes不會自動備份此目錄
這個目錄下有兩個子目錄:Caches 和 Preferences
Caches可以重新下載下傳或者重新生成的資料應該儲存在 <Application_Home>/Library/Caches 目錄下面。舉個例子,比如雜志、新聞、地圖應用使用的資料庫緩存檔案和可下載下傳内容應該儲存到這個檔案夾。此目錄下不會再應用退出時删除。
Preferences 目錄包含應用程式的偏好設定檔案。您不應該直接建立偏好設定檔案,而是應該使用NSUserDefaults類來取得和設定應用程式的偏好
tmp:
隻是臨時使用的資料應該儲存到 <Application_Home>/tmp 檔案夾。盡管 iCloud 不會備份這些檔案,但在應用在使用完這些資料之後要注意随時删除,避免占用使用者裝置的空間,儲存應用程式再次啟動過程中不需要的資訊
二、檔案的寫入與讀取
得到沙盒路徑的方法
寫在SandBoxPaths中,外部可調用
//得到docments路徑
+(NSString *)documentsPath
{
NSArray *docArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return docArray[0];
}
//library
+(NSString *)libraryPath
{
NSArray *libArray = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
return libArray[0];
}
//library/cache
+(NSString *)cachePath
{
NSArray *cacheArray = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
return cacheArray[0];
}
//library/perfrence 系統維護的,一般人為不會去動這個檔案夾
+(NSString *)perfrencePath
{
NSArray *perfrenceArr = NSSearchPathForDirectoriesInDomains(NSPreferencePanesDirectory, NSUserDomainMask, YES);
return perfrenceArr[0];
}
//也可以通過拼接方式得到library/perfrence
NSArray *libPath = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSLog(@"%@",libPath[0]);
NSString *perPath = [libPath[0]stringByAppendingString:@"Preferences"];
//tmp路徑
+(NSString *)tmpPath
{
NSString *tmpStr = NSTemporaryDirectory();
return tmpStr;
}
//app路徑
NSString *appPath = [NSBundle mainBundle].resourcePath;
//程式包中的一個圖檔資源
NSString *imagePath = [[NSBundle mainBundle]pathForResource:@"myImage" ofType:@"png"];
通過拼接方式獲得路徑
//沙盒主路徑
NSString *homeStrPath = NSHomeDirectory();
NSLog(@"homePath = %@",homeStrPath);
//得到沙盒下的lib路徑
NSString *libPath = [homeStrPath stringByAppendingPathComponent:@"Library"];
NSLog(@"lib : %@",libPath);
//得到沙盒下document路徑
NSString *docPath = [homeStrPath stringByAppendingPathComponent:@"Documents"];
寫入和讀取檔案
//寫入檔案
-(void)writeString
{
NSString *str = @"将要寫入的資料";
//拼接字元串,構造資料将要存儲的位置
NSString *path = [[SandBoxPaths documentsPath]stringByAppendingString:@"/text.txt"];
//将資料寫入路徑下
//核心方法writeToFile,可以寫入字元串,數組,字典等
//atomically:YES,會先寫入一個中間臨時檔案,完成後再存入目标檔案
//已經存在會覆寫
BOOL isWrite = [str writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];
if (isWrite) {
NSLog(@"寫入成功,%@",path);
}
else
NSLog(@"寫入失敗");
}
//讀取檔案
-(void)readFile:(NSString*)path
{
//path的檔案裡面是什麼格式,就用什麼格式去取
//路徑就是定位到檔案的路徑
//NSArray *arr = [NSArray arrayWithContentsOfFile:path];
NSString *str = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
NSLog(@"讀取:%@",str);
}
三、檔案管理器NSFileManger與檔案對接器NSFileHandle,還有歸檔
1.檔案管理器
檔案管理器主要是對檔案進行建立、删除、改名、擷取檔案資訊等操作
檔案連接配接器主要對檔案内容進行讀取和寫入
//FILEmanager使用
-(void)myFilemanager
{
//得到路徑
NSString* path = [[SandBoxPaths documentsPath]stringByAppendingPathComponent:@"test"];
NSString *pathTest = [[SandBoxPaths documentsPath]stringByAppendingPathComponent:@"text.txt"];
NSString *pathDst = [[SandBoxPaths documentsPath]stringByAppendingPathComponent:@"test/text1.txt"];
NSString *pathStrFile = [[SandBoxPaths documentsPath]stringByAppendingPathComponent:@"file.txt"];
NSString *str = @"sssssssssssss";
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
//建立檔案管理器
NSFileManager *fileM = [NSFileManager defaultManager];
//建立目錄
//路徑Path
//是否自動建立
//attributes權限設定
BOOL isCreate = [fileM createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
if (isCreate) {
NSLog(@"成功:,%@",path);
}
else
NSLog(@"失敗");
//建立檔案并寫入資料
[fileM createFileAtPath:pathStrFile contents: data attributes:nil];
//從檔案中讀取
NSData *getData = [fileM contentsAtPath:pathStrFile];
NSLog(@"%@",[[NSString alloc]initWithData:getData encoding:NSUTF8StringEncoding]);
//移動檔案位置
BOOL isMove = [fileM moveItemAtPath:pathTest toPath:pathDst error:nil];
if (isMove) {
NSLog(@"成功移動");
}
else
NSLog(@"移動失敗");
//複制檔案
BOOL isCopy = [fileM copyItemAtPath:pathDst toPath:pathTest error:nil];
if (isCopy) {
NSLog(@"複制成功");
}
else
NSLog(@"複制失敗");
//比較檔案是否相同
BOOL isEqual = [fileM contentsEqualAtPath:pathTest andPath:pathDst];
if (isEqual) {
NSLog(@"檔案内容相同");
}
else
NSLog(@"檔案内容不同");
//移除檔案
BOOL isRemove = [fileM removeItemAtPath:pathDst error:nil];
if (isRemove) {
NSLog(@"移除成功");
}
else
NSLog(@"移除失敗");
//檔案是否存在
BOOL isExist = [fileM fileExistsAtPath:pathDst];
if (isExist) {
NSLog(@"檔案存在");
}
else
NSLog(@"檔案不存在");
}
2.檔案對接器,NSFileHandle
//NSfileHandle的使用
//首次使用時,要先建立需要操作的檔案
NSString *path = [[SandBoxPaths documentsPath]stringByAppendingPathComponent:@"fileHandele.txt"];
NSString *contentStr = @"12345678901234567890";
NSData *contentData = [contentStr dataUsingEncoding:NSUTF8StringEncoding];
NSFileManager *manager = [NSFileManager defaultManager];
//先判斷檔案是否存在,如果不存在再建立
if ([manager fileExistsAtPath:path]) {
NSLog(@"檔案已經存在");
}
else
{
//建立檔案
[manager createFileAtPath:path contents:contentData attributes:nil];
}
//建立準備讀取的handle對象
NSFileHandle *readHandle =[NSFileHandle fileHandleForReadingAtPath:path];
//得到可讀的内容的長度,節點移動到末尾
NSUInteger length = [[readHandle availableData]length];
NSLog(@"%ld",length);
//跳到指定的偏移量
[readHandle seekToFileOffset:5];
//讀取特定長度,從目前節點到指定長度,節點移動到讀取末尾
NSData *lengthData = [readHandle readDataOfLength:11];
NSString *lengthStr = [[NSString alloc]initWithData:lengthData encoding:NSUTF8StringEncoding];
NSLog(@"lengthStr = %@",lengthStr);
//得到從目前節點到最後的可讀取的内容,節點移動到最後
NSData *availableData = [readHandle availableData];
NSString *availableStr = [[NSString alloc]initWithData:availableData encoding:NSUTF8StringEncoding];
NSLog(@"avStr = %@",availableStr);
//跳到指定的偏移量,移動回2處,也就是從第三個位置開始讀
[readHandle seekToFileOffset:2];
//完整的讀取檔案,從目前節點讀到末尾
NSData *endData = [readHandle readDataToEndOfFile];
NSString *endStr = [[NSString alloc]initWithData:endData encoding:NSUTF8StringEncoding];
NSLog(@"endStr = %@",endStr);
//建立一個可以寫入的fileHandle
NSFileHandle *writeHandle = [NSFileHandle fileHandleForWritingAtPath:path];
//改變偏移量
[writeHandle seekToFileOffset:4];
//寫入
NSString *writeStr = @"abc";
NSData *writeData = [writeStr dataUsingEncoding:NSUTF8StringEncoding];
[writeHandle writeData:writeData];
//跳到指定的偏移量
[readHandle seekToFileOffset:0];
//讀取
NSString *allStr = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
NSLog(@"allStr = %@",allStr);
3.歸檔與反歸檔
歸檔的作用,就是将複雜對象存儲進檔案,複雜對象就是如我們自己定義的person類,student類,不能用writeToFile寫入檔案中。
我們需要先将複雜對象轉換為NSData類型,用writeToFile存入檔案
取出時再通過反歸檔,把NSData類型恢複成複雜對象
歸檔時,person類等要遵守<NSCoding>協定,實作歸檔和反歸檔的方法
#import "Person.h"
@implementation Person
//序列化操作,歸檔
//實際上是對目前類對象所有的屬性進行歸檔
//協定方法在我們歸檔的時候自動調用
-(void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeObject:self.sex forKey:@"sex"];
}
//反歸檔
-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
self.name = [aDecoder decodeObjectForKey:@"name"];
self.sex = [aDecoder decodeObjectForKey:@"sex"];
}
return self;
}
#pragma mark -- 歸檔,反歸檔
-(void)archiver
{
Person *firstPer = [[Person alloc]init];
firstPer.name = @"wna";
firstPer.sex = @"m";
//建立一個mutableData,用于儲存歸檔後的對象
NSMutableData *mutableData = [NSMutableData data];
//建立歸檔工具
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:mutableData];
//歸檔
[archiver encodeObject:firstPer forKey:@"person"];
//結束
//隻有調用了此方法,才會将歸檔好的對象裝換為NSData
[archiver finishEncoding];
//拼接寫入沙盒路徑
NSString *cachesPath2 = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)objectAtIndex:0]
stringByAppendingPathComponent:@"person.txt"];
//寫入沙盒
[mutableData writeToFile:cachesPath2 atomically:YES];
}
//反歸檔
-(void)unArchiver
{
//拼接寫入沙盒路徑
NSString *cachesPath2 = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)objectAtIndex:0]
stringByAppendingPathComponent:@"person.txt"];
//反歸檔
//從檔案路徑讀取
NSData *fileData = [NSData dataWithContentsOfFile:cachesPath2];
//反歸檔工具
NSKeyedUnarchiver *unArchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:fileData];
//反歸檔成對象,key要對應
Person *secondPer = [unArchiver decodeObjectForKey:@"person"];
//反歸檔結束
[unArchiver finishDecoding];
NSLog(@"person = %@",secondPer.name);
}
這裡再附加一個把UIImage轉換為NSString的方法
//UIImage轉換為NSString
-(NSString*)imageToStringWithImage:(UIImage*)image
{
//先将image轉換為data類型,後面參數是品質
NSData *imageData = UIImageJPEGRepresentation(image, 1.0);
//再講NSData轉換為NSString
NSString *string = [imageData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
return string;
}
//将base64的字元串轉換為圖檔
-(UIImage*)base64StringToImage:(NSString*)base64Str
{
//将字元串轉換為NSData
NSData *imageData = [[NSData alloc]initWithBase64EncodedString:base64Str
options:NSDataBase64DecodingIgnoreUnknownCharacters];
//NSData到圖檔
UIImage *image = [UIImage imageWithData:imageData];
return image;
}