一、沙盒機(jī)制
1.什么是沙盒
通俗的說,就是將一個(gè)應(yīng)用程序的所有的非代碼文件放在一個(gè)文件夾里(沙盒),應(yīng)用程序只能從該文件系統(tǒng)讀取文件,不能去其他地方訪問。
每一個(gè)iOS應(yīng)用程序都會(huì)為自己創(chuàng)建一個(gè)文件系統(tǒng)目錄。這個(gè)獨(dú)立封閉、安全的空間,叫做沙盒。
2.打開模擬器的沙盒目錄
點(diǎn)擊finder----點(diǎn)擊菜單欄的前往----按住alt,出現(xiàn)了隱藏的資源庫選項(xiàng)----點(diǎn)擊資源庫----developer----CoreSimulator----Devices,然后發(fā)現(xiàn)這里有很多的一長串字母的文件,
根據(jù)時(shí)間找到最新的一個(gè)文件打開。
或者在終端寫 : defaults write com.apple.finder AppleShowAllFiles -bool true ,也可以顯示隱藏文件
看到里面有三個(gè)并列文件夾 Library,Documents,tmp
Document:
只有用戶生成的文件、其他數(shù)據(jù)及其他程序不能重新創(chuàng)建的文件,應(yīng)該保存在<Application_Home>/Documents 目錄下面,并將通過iCloud自動(dòng)備份,應(yīng)該將所有的應(yīng)用程序數(shù)據(jù)文件寫入到這個(gè)目錄下。
Library
iTunes不會(huì)自動(dòng)備份此目錄
這個(gè)目錄下有兩個(gè)子目錄:Caches 和 Preferences
Caches
可以重新下載或者重新生成的數(shù)據(jù)應(yīng)該保存在 <Application_Home>/Library/Caches 目錄下面。舉個(gè)例子,比如雜志、新聞、地圖應(yīng)用使用的數(shù)據(jù)庫緩存文件和可下載內(nèi)容應(yīng)該保存到這個(gè)文件夾。此目錄下不會(huì)再應(yīng)用退出時(shí)刪除。
Preferences
目錄包含應(yīng)用程序的偏好設(shè)置文件。您不應(yīng)該直接創(chuàng)建偏好設(shè)置文件,而是應(yīng)該使用NSUserDefaults類來取得和設(shè)置應(yīng)用程序的偏好
tmp
只是臨時(shí)使用的數(shù)據(jù)應(yīng)該保存到 <Application_Home>/tmp 文件夾。盡管 iCloud 不會(huì)備份這些文件,但在應(yīng)用在使用完這些數(shù)據(jù)之后要注意隨時(shí)刪除,避免占用用戶設(shè)備的空間,保存應(yīng)用程序再次啟動(dòng)過程中不需要的信息
二、文件的寫入與讀取
得到沙盒路徑的方法
寫在SandBoxPaths中,外部可調(diào)用
//得到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 系統(tǒng)維護(hù)的,一般人為不會(huì)去動(dòng)這個(gè)文件夾
+(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;
//程序包中的一個(gè)圖片資源
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 = @"將要寫入的數(shù)據(jù)";
//拼接字符串,構(gòu)造數(shù)據(jù)將要存儲(chǔ)的位置
NSString *path = [[SandBoxPaths documentsPath]stringByAppendingString:@"/text.txt"];
//將數(shù)據(jù)寫入路徑下
//核心方法writeToFile,可以寫入字符串,數(shù)組,字典等
//atomically:YES,會(huì)先寫入一個(gè)中間臨時(shí)文件,完成后再存入目標(biāo)文件
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.文件管理器
文件管理器主要是對文件進(jìn)行創(chuàng)建、刪除、改名、獲取文件信息等操作
文件連接器主要對文件內(nèi)容進(jìn)行讀取和寫入
//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];
//創(chuàng)建文件管理器
NSFileManager *fileM = [NSFileManager defaultManager];
//創(chuàng)建目錄
//路徑Path
//是否自動(dòng)創(chuàng)建
//attributes權(quán)限設(shè)置
BOOL isCreate = [fileM createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
if (isCreate) {
NSLog(@"成功:,%@",path);
}
else
NSLog(@"失敗");
//創(chuàng)建文件并寫入數(shù)據(jù)
[fileM createFileAtPath:pathStrFile contents: data attributes:nil];
//從文件中讀取
NSData *getData = [fileM contentsAtPath:pathStrFile];
NSLog(@"%@",[[NSString alloc]initWithData:getData encoding:NSUTF8StringEncoding]);
//移動(dòng)文件位置
BOOL isMove = [fileM moveItemAtPath:pathTest toPath:pathDst error:nil];
if (isMove) {
NSLog(@"成功移動(dòng)");
}
else
NSLog(@"移動(dòng)失敗");
//復(fù)制文件
BOOL isCopy = [fileM copyItemAtPath:pathDst toPath:pathTest error:nil];
if (isCopy) {
NSLog(@"復(fù)制成功");
}
else
NSLog(@"復(fù)制失敗");
//比較文件是否相同
BOOL isEqual = [fileM contentsEqualAtPath:pathTest andPath:pathDst];
if (isEqual) {
NSLog(@"文件內(nèi)容相同");
}
else
NSLog(@"文件內(nèi)容不同");
//移除文件
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的使用
//首次使用時(shí),要先創(chuàng)建需要操作的文件
NSString *path = [[SandBoxPaths documentsPath]stringByAppendingPathComponent:@"fileHandele.txt"];
NSString *contentStr = @"12345678901234567890";
NSData *contentData = [contentStr dataUsingEncoding:NSUTF8StringEncoding];
NSFileManager *manager = [NSFileManager defaultManager];
//先判斷文件是否存在,如果不存在再創(chuàng)建
if ([manager fileExistsAtPath:path]) {
NSLog(@"文件已經(jīng)存在");
}
else
{
//創(chuàng)建文件
[manager createFileAtPath:path contents:contentData attributes:nil];
}
//創(chuàng)建準(zhǔn)備讀取的handle對象
NSFileHandle *readHandle =[NSFileHandle fileHandleForReadingAtPath:path];
//得到可讀的內(nèi)容的長度,節(jié)點(diǎn)移動(dòng)到末尾
NSUInteger length = [[readHandle availableData]length];
NSLog(@"%ld",length);
//跳到指定的偏移量
[readHandle seekToFileOffset:5];
//讀取特定長度,從當(dāng)前節(jié)點(diǎn)到指定長度,節(jié)點(diǎn)移動(dòng)到讀取末尾
NSData *lengthData = [readHandle readDataOfLength:11];
NSString *lengthStr = [[NSString alloc]initWithData:lengthData encoding:NSUTF8StringEncoding];
NSLog(@"lengthStr = %@",lengthStr);
//得到從當(dāng)前節(jié)點(diǎn)到最后的可讀取的內(nèi)容,節(jié)點(diǎn)移動(dòng)到最后
NSData *availableData = [readHandle availableData];
NSString *availableStr = [[NSString alloc]initWithData:availableData encoding:NSUTF8StringEncoding];
NSLog(@"avStr = %@",availableStr);
//跳到指定的偏移量,移動(dòng)回2處,也就是從第三個(gè)位置開始讀
[readHandle seekToFileOffset:2];
//完整的讀取文件,從當(dāng)前節(jié)點(diǎn)讀到末尾
NSData *endData = [readHandle readDataToEndOfFile];
NSString *endStr = [[NSString alloc]initWithData:endData encoding:NSUTF8StringEncoding];
NSLog(@"endStr = %@",endStr);
//創(chuàng)建一個(gè)可以寫入的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.歸檔與反歸檔
歸檔的作用,就是將復(fù)雜對象存儲(chǔ)進(jìn)文件,復(fù)雜對象就是如我們自己定義的person類,student類,不能用writeToFile寫入文件中。
我們需要先將復(fù)雜對象轉(zhuǎn)換為NSData類型,用writeToFile存入文件
取出時(shí)再通過反歸檔,把NSData類型恢復(fù)成復(fù)雜對象
歸檔時(shí),person類等要遵守<NSCoding>協(xié)議,實(shí)現(xiàn)歸檔和反歸檔的方法
import "Person.h"
@implementation Person
//序列化操作,歸檔
//實(shí)際上是對當(dāng)前類對象所有的屬性進(jìn)行歸檔
//協(xié)議方法在我們歸檔的時(shí)候自動(dòng)調(diào)用
-(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";
//創(chuàng)建一個(gè)mutableData,用于保存歸檔后的對象
NSMutableData *mutableData = [NSMutableData data];
//創(chuàng)建歸檔工具
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:mutableData];
//歸檔
[archiver encodeObject:firstPer forKey:@"person"];
//結(jié)束
//只有調(diào)用了此方法,才會(huì)將歸檔好的對象裝換為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要對應(yīng)
Person *secondPer = [unArchiver decodeObjectForKey:@"person"];
//反歸檔結(jié)束
[unArchiver finishDecoding];
NSLog(@"person = %@",secondPer.name);
}
這里再附加一個(gè)把UIImage轉(zhuǎn)換為NSString的方法
//UIImage轉(zhuǎn)換為NSString
-(NSString)imageToStringWithImage:(UIImage)image
{
//先將image轉(zhuǎn)換為data類型,后面參數(shù)是品質(zhì)
NSData imageData = UIImageJPEGRepresentation(image, 1.0);
//再講NSData轉(zhuǎn)換為NSString
NSString string = [imageData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
return string;
}
//將base64的字符串轉(zhuǎn)換為圖片
-(UIImage)base64StringToImage:(NSString)base64Str
{
//將字符串轉(zhuǎn)換為NSData
NSData *imageData = [[NSData alloc]initWithBase64EncodedString:base64Str
options:NSDataBase64DecodingIgnoreUnknownCharacters];
//NSData到圖片
UIImage *image = [UIImage imageWithData:imageData];
return image;
}