標籤:
沙箱詳解
1、IOS沙箱機制
IOS應用程式只能在為該改程式建立的檔案系統中讀取檔案,不可以去其它地方訪問,此地區被成為沙箱,所以所有的非代碼檔案都要儲存在此,例像,表徵圖,聲音,映像,屬性列表,文字檔等。
1.1、每個應用程式都有自己的儲存空間
1.2、應用程式不能翻過自己的圍牆去訪問別的儲存空間的內容
1.3、應用程式請求的資料都要通過許可權檢測,假如不合格話,不會被允許存取。
通過這張圖只能從表層上理解sandbox是一種安全體系,應用程式的所有操作都要通過這個體系來執行,其中核心內容是:sandbox對應用程式執行各種操作的許可權限制。
2、開啟模擬器沙箱目錄
下面看看模擬器的沙箱檔案夾在mac電腦上的什麼位置。
檔案都在個人使用者名稱檔案夾下的一個隱藏檔案夾裡,中文叫資產庫,他的目錄其實是Library。
2.1 方法1、可以設定顯示隱藏檔案,然後在Finder下直接開啟。設定查看隱藏檔案的方法如下:開啟終端,輸入命名
顯示Mac隱藏檔案的命令:defaults write com.apple.finder AppleShowAllFiles -bool true
隱藏Mac隱藏檔案的命令:defaults write com.apple.finder AppleShowAllFiles -bool false
輸完單擊Enter鍵,退出終端,
重新啟動Finder就可以了重啟Finder:按一下滑鼠視窗左上方的蘋果標誌-->強制退出-->Finder-->
現在能看到資產庫檔案夾了。
開啟資產庫後找到/Application Support/iPhone Simulator/檔案夾。這裡面就是模擬器的各個程式的沙箱目錄了。
2.2 方法2、這種方法更方便,在Finder上點->前往->前往檔案夾,輸入/Users/username/Library/Application Support/iPhone Simulator/ 前往。
username這裡寫你的使用者名稱。
3、目錄結構
預設情況下,每個沙箱含有3個檔案夾:Documents, Library 和 tmp。因為應用的沙箱機制,應用只能在幾個目錄下讀寫檔案
Documents:蘋果建議將程式中建立的或在程式中瀏覽到的檔案資料儲存在該目錄下,iTunes備份和恢複的時候會包括此目錄
Library:儲存程式的預設設定或其它狀態資訊;
Library/Caches:存放快取檔案,iTunes不會備份此目錄,此目錄下檔案不會在應用退出刪除
tmp:提供一個即時建立臨時檔案的地方。
iTunes在與iPhone同步時,備份所有的Documents和Library檔案。
iPhone在重啟時,會丟棄所有的tmp檔案。
我們建立一個IosSandbox的項目來展開沙箱和檔案讀寫等操作的練習。
建立後找到模擬器上對應的目錄,
這是目錄全展開了。
這是上面提到的三個目錄 :Documents、Library、 tmp
下篇介紹目錄路徑擷取和檔案操作
我們看看如何擷取應用程式沙箱目錄。包括真機的沙箱的目錄。
1、擷取程式的Home目錄
NSString *homeDirectory = NSHomeDirectory(); NSLog(@"path:%@", homeDirectory); |
列印結果:
2012-06-17 14:00:06.098 IosSandbox[3536:f803] /Users/rongfzh/Library/Application Support/iPhone Simulator/5.1/Applications/3B8EC78A-5EEE-4C2F-B0CB-4C3F02B996D2 |
那在真機上的目錄有是怎麼樣的呢?我們看看
2012-06-17 14:25:47.059 IosSandbox[4281:f803] /var/mobile/Applications/3B8EC78A-5EEE-4C2F-B0CB-4C3F02B996D2
可見,真機上的目錄是/var/mobile/Applications/這個目錄下的,和模擬器不一樣。這個是Home目錄,其他的子目錄和模擬器一樣。
2、擷取document目錄
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *path = [paths objectAtIndex:0]; NSLog(@"path:%@", path); |
列印結果
2012-06-17 14:00:06.099 IosSandbox[3536:f803] path:/Users/rongfzh/Library/Application Support/iPhone Simulator/5.1/Applications/3B8EC78A-5EEE-4C2F-B0CB-4C3F02B996D2/Documents |
3、擷取Cache目錄
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); NSString *path = [paths objectAtIndex:0]; NSLog(@"%@", path); |
列印結果:
2012-06-17 14:03:50.431 IosSandbox[3628:f803] /Users/rongfzh/Library/Application Support/iPhone Simulator/5.1/Applications/3B8EC78A-5EEE-4C2F-B0CB-4C3F02B996D2/Library/Caches |
4、擷取Library目錄
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); NSString *path = [paths objectAtIndex:0]; NSLog(@"%@", path); |
列印結果:
2012-06-17 14:07:17.544 IosSandbox[3733:f803] /Users/rongfzh/Library/Application Support/iPhone Simulator/5.1/Applications/3B8EC78A-5EEE-4C2F-B0CB-4C3F02B996D2/Library |
5、擷取Tmp目錄
NSString *tmpDir = NSTemporaryDirectory(); NSLog(@"%@", tmpDir); |
列印結果:
2012-06-17 14:08:07.824 IosSandbox[3782:f803] /var/folders/g7/246bh79130zblw0yjjtc55cw0000gn/T/ |
6、寫入檔案
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *docDir = [paths objectAtIndex:0]; if (!docDir) { NSLog(@"Documents 目錄未找到"); } NSArray *array = [[NSArray alloc] initWithObjects:@"內容",@"content",nil]; NSString *filePath = [docDir stringByAppendingPathComponent:@"testFile.txt"]; [array writeToFile:filePath atomically:YES]; |
註:我們在真機上也運行一下,把檔案寫入,下一步從真機上把內容讀取出來。
寫入輸入 array ,裡面是兩個字串,一會我們讀出來列印。
寫入我們在程式沙箱目錄下看到檔案 testFile.txt
開啟檔案看到的內容是這樣的,是個xml格式的plist檔案,資料格式儲存了內容。
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><array><string>內容</string><string>content</string></array></plist> |
7、讀取檔案
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *docDir = [paths objectAtIndex:0]; NSString *filePath = [docDir stringByAppendingPathComponent:@"testFile.txt"]; NSArray *array = [[NSArray alloc]initWithContentsOfFile:filePath]; NSLog(@"%@", array); |
列印結果:
把上面的檔案解析後,把內容列印出來了。
2012-06-17 14:14:46.249 IosSandbox[3918:f803] ( "\U5185\U5bb9", content) |
真機上讀取並列印檔案路徑:
2012-06-17 14:25:47.059 IosSandbox[4281:f803] /var/mobile/Applications/3B8EC78A-5EEE-4C2F-B0CB-4C3F02B996D2/Documents/testFile.txt
(
"\U5185\U5bb9",
content
)
真機上也能寫入和列印。
我們看看NSFileManager如何使用。包括建立檔案,目錄,刪除,遍曆目錄等。
1、在Documents裡建立目錄
建立一個叫test的目錄,先找到Documents的目錄,
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSLog(@"documentsDirectory%@",documentsDirectory); NSFileManager *fileManager = [NSFileManager defaultManager]; NSString *testDirectory = [documentsDirectory stringByAppendingPathComponent:@"test"]; // 建立目錄 [fileManager createDirectoryAtPath:testDirectory withIntermediateDirectories:YES attributes:nil error:nil]; |
啟動程式,這時候目錄就建立了:
2、在test目錄下建立檔案
建立檔案怎麼辦呢?接著上面的代碼 testPath 要用stringByAppendingPathComponent拼接上你要產生的檔案名稱,比如test00.txt。這樣才能在test下寫入檔案。
testDirectory是上面代碼產生的路徑哦,不要忘了。我往test檔案夾裡寫入三個檔案,test00.txt ,test22.txt,text.33.txt。內容都是寫入內容,write String。
實現代碼如下:
NSString *testPath = [testDirectory stringByAppendingPathComponent:@"test00.txt"]; NSString *testPath2 = [testDirectory stringByAppendingPathComponent:@"test22.txt"]; NSString *testPath3 = [testDirectory stringByAppendingPathComponent:@"test33.txt"]; NSString *string = @"寫入內容,write String";[fileManager createFileAtPath:testPath contents:[string dataUsingEncoding:NSUTF8StringEncoding] attributes:nil];[fileManager createFileAtPath:testPath2 contents:[string dataUsingEncoding:NSUTF8StringEncoding] attributes:nil];[fileManager createFileAtPath:testPath3 contents:[string dataUsingEncoding:NSUTF8StringEncoding] attributes:nil]; |
看下面的圖,三個檔案都出來了,內容也對。
在Documents目錄下建立就更簡單了,不用加test就ok了
3、擷取目錄列裡所有檔案名稱
兩種方法擷取:subpathsOfDirectoryAtPath 和 subpathsAtPath
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSLog(@"documentsDirectory%@",documentsDirectory); NSFileManager *fileManage = [NSFileManager defaultManager]; NSString *myDirectory = [documentsDirectory stringByAppendingPathComponent:@"test"]; NSArray *file = [fileManage subpathsOfDirectoryAtPath: myDirectory error:nil]; NSLog(@"%@",file); NSArray *files = [fileManage subpathsAtPath: myDirectory ]; NSLog(@"%@",files); |
擷取上面剛才test檔案夾裡的檔案名稱
列印結果
2012-06-17 23:23:19.684 IosSandbox[947:f803] fileList:( ".DS_Store", "test00.txt", "test22.txt", "test33.txt")2012-06-17 23:23:19.686 IosSandbox[947:f803] fileLit( ".DS_Store", "test00.txt", "test22.txt", "test33.txt") |
兩個方法都可以,隱藏的檔案也列印出來了。
4、fileManager使用操作目前的目錄
//建立檔案管理工具 NSFileManager *fileManager = [NSFileManager defaultManager]; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; //更改到待操作的目錄下 [fileManager changeCurrentDirectoryPath:[documentsDirectory stringByExpandingTildeInPath]]; //建立檔案fileName檔案名稱,contents檔案的內容,如果開始沒有內容可以設定為nil,attributes檔案的屬性,初始為nil NSString * fileName = @"testFileNSFileManager.txt"; NSArray *array = [[NSArray alloc] initWithObjects:@"hello world",@"hello world1", @"hello world2",nil]; [fileManager createFileAtPath:fileName contents:array attributes:nil]; |
這樣就建立了testFileNSFileManager.txt並把三個hello world寫入檔案了
changeCurrentDirectoryPath目錄更改到當前操作目錄時,做檔案讀寫就很方便了,不用加上全路徑
5、刪除檔案
接上面的代碼,remove就ok了。
| [fileManager removeItemAtPath:fileName error:nil]; |
6、混合資料的讀寫
用NSMutableData建立混合資料,然後寫到檔案裡。並按資料的類型把資料讀出來
6.1寫入資料:
NSString * fileName = @"testFileNSFileManager.txt"; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; //擷取檔案路徑 NSString *path = [documentsDirectory stringByAppendingPathComponent:fileName]; //待寫入的資料 NSString *temp = @"nihao 世界"; int dataInt = 1234; float dataFloat = 3.14f; //建立資料緩衝 NSMutableData *writer = [[NSMutableData alloc] init]; //將字串添加到緩衝中 [writer appendData:[temp dataUsingEncoding:NSUTF8StringEncoding]]; //將其他資料添加到緩衝中 [writer appendBytes:&dataInt length:sizeof(dataInt)]; [writer appendBytes:&dataFloat length:sizeof(dataFloat)]; //將緩衝的資料寫入到檔案中 [writer writeToFile:path atomically:YES]; |
我們看看資料怎麼樣了:
我們看到後面的是亂碼,那是中文被轉成了NSData後,還有int float的二進位
6.2讀取剛才寫入的資料:
//讀取資料: int intData; float floatData = 0.0; NSString *stringData; NSData *reader = [NSData dataWithContentsOfFile:path]; stringData = [[NSString alloc] initWithData:[reader subdataWithRange:NSMakeRange(0, [temp length])] encoding:NSUTF8StringEncoding]; [reader getBytes:&intData range:NSMakeRange([temp length], sizeof(intData))]; [reader getBytes:&floatData range:NSMakeRange([temp length] + sizeof(intData), sizeof(floatData))]; NSLog(@"stringData:%@ intData:%d floatData:%f", stringData, intData, floatData); |
列印出來的結果:
2012-06-17 23:51:14.723 IosSandbox[1285:f803] stringData:nihao hello! intData:1234332 floatData:3.140000
這裡把寫入的漢字改成了 hello。因為[temp length]算長度是,把中文算成一位了,出來的結果有誤。
iOS開發——資料持久化OC篇&(一)沙箱詳解