前言
因為這一段時間有需求需要用到文件的存取操作培己,而之前基本上對于本地數(shù)據(jù)的存儲就是簡單數(shù)據(jù)用NSUserDefaults碳蛋,復(fù)雜點的用歸檔,再復(fù)雜一點的用sql省咨。對于文件存取了解不多∷嗟埽現(xiàn)在需求來了,沒辦法零蓉,只能脫了褲子就是...笤受。
文件存儲分三節(jié)來說:
- 簡單的類型操作,比如NSString敌蜂,NSData箩兽,NSArray之類的問價存取
- NSFileManager,NSFileHandle類進(jìn)行文件的存儲
- FILE進(jìn)行文件的存儲
正文
NSFileManager
NSFileManager 是iOS的文件管理的一個類章喉,主要是對文件進(jìn)行創(chuàng)建汗贫,刪除身坐,獲取文件信息等操作。有一點要知道落包,NSFileManager的使用級別是文件部蛇,他不能對文件里面的內(nèi)容做什么處理操作。你想修改一個txt里面的數(shù)據(jù)咐蝇,對不起涯鲁,NSFileManager幫助不了你的,這時候就需要NSFileHandle來救場有序,一會再說這個類抹腿。
NSFileManager 里面的方法有很多,平常我(low??程序??)使用到了基本上就幾個:
//創(chuàng)建一個文件笔呀,并給文件內(nèi)容
- (BOOL)createFileAtPath:(NSString *)path contents:(nullable NSData *)data attributes:(nullable NSDictionary<NSString *, id> *)attr;
//創(chuàng)建一個文件夾
- (BOOL)createDirectoryAtPath:(NSString *)path withIntermediateDirectories:(BOOL)createIntermediates attributes:(nullable NSDictionary<NSString *, id> *)attributes error:(NSError **)error NS_AVAILABLE(10_5, 2_0);
//判斷文件是否存在
- (BOOL)fileExistsAtPath:(NSString *)path;
- (BOOL)fileExistsAtPath:(NSString *)path isDirectory:(nullable BOOL *)isDirectory;
//文件的復(fù)制幢踏,移動髓需,刪除操作
- (BOOL)copyItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error NS_AVAILABLE(10_5, 2_0);
- (BOOL)moveItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error NS_AVAILABLE(10_5, 2_0);
- (BOOL)removeItemAtPath:(NSString *)path error:(NSError **)error NS_AVAILABLE(10_5, 2_0);
舉個栗子:
//1 存儲路徑的獲取
NSString *path1 = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/file_test1.txt"];
//2 創(chuàng)建文件需要一個文件管理對象
NSFileManager *manager = [NSFileManager defaultManager];
//3 創(chuàng)建文件
NSString *testStr = @"這是一個文件測試";
[manager createFileAtPath:path1 contents:[testStr dataUsingEncoding:NSUTF8StringEncoding] attributes:nil];
栗子標(biāo)準(zhǔn)了步驟许师,萬年按照步驟走,就不會有事僚匆,思路最重要微渠。
可以看到,NSFileManager需要單例創(chuàng)建, 然后調(diào)用創(chuàng)建文件的方法
- (BOOL)createFileAtPath:(NSString *)path contents:(nullable NSData *)data attributes:(nullable NSDictionary<NSString *, id> *)attr;
這個方法需要傳入的數(shù)據(jù)為NSData類型咧擂,所以要進(jìn)行一次NSData的轉(zhuǎn)換逞盆。
到底創(chuàng)建成功了沒有呢,我們?nèi)ノ募穆窂讲樵円幌?br>
效果:
說明文件已經(jīng)創(chuàng)建成功了松申。那么云芦,我們怎么去查詢這個文件的一些信息嗎。這還不簡單贸桶,點擊文件->右鍵->顯示簡介舅逸,搞定了···。??????皇筛,出門左拐琉历,不謝。
正確姿勢:
//獲取文件信息
NSDictionary *dic = [manager attributesOfItemAtPath:path1 error:nil];
[dic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
NSLog(@"key = %@,value = %@",key,obj);
}];
然后輸出獲得的屬性字典水醋,查看所有的文件屬性:
2017-09-08 13:25:14.782 文件讀寫Demo[2532:368804] key = NSFileOwnerAccountID,value = 501
2017-09-08 13:25:14.783 文件讀寫Demo[2532:368804] key = NSFileSystemFileNumber,value = 23349726
2017-09-08 13:25:14.783 文件讀寫Demo[2532:368804] key = NSFileExtensionHidden,value = 0
2017-09-08 13:25:14.783 文件讀寫Demo[2532:368804] key = NSFileSystemNumber,value = 16777220
2017-09-08 13:25:14.783 文件讀寫Demo[2532:368804] key = NSFileSize,value = 24
2017-09-08 13:25:14.783 文件讀寫Demo[2532:368804] key = NSFileGroupOwnerAccountID,value = 20
2017-09-08 13:25:14.784 文件讀寫Demo[2532:368804] key = NSFilePosixPermissions,value = 420
2017-09-08 13:25:14.786 文件讀寫Demo[2532:368804] key = NSFileCreationDate,value = 2017-09-08 05:25:14 +0000
2017-09-08 13:25:14.786 文件讀寫Demo[2532:368804] key = NSFileType,value = NSFileTypeRegular
2017-09-08 13:25:14.787 文件讀寫Demo[2532:368804] key = NSFileGroupOwnerAccountName,value = staff
2017-09-08 13:25:14.787 文件讀寫Demo[2532:368804] key = NSFileReferenceCount,value = 1
2017-09-08 13:25:14.787 文件讀寫Demo[2532:368804] key = NSFileModificationDate,value = 2017-09-08 05:25:14 +0000
如果旗笔,我們文件創(chuàng)建成功了,但是卻發(fā)現(xiàn)路徑錯了拄踪,那應(yīng)該怎么辦呢蝇恶?不用怕,NSFileManager可以幫你惶桐。
//6 移動后的文件路徑位置
NSString *resultPath = [cachesPath stringByAppendingPathComponent:[path lastPathComponent]];
//7 移動文件
[manager moveItemAtPath:path toPath:resultPath error:nil];
這樣撮弧,咱們的文件就被移動走了的猛。
其他的比如,查詢文件是否存在之類的操作想虎,同學(xué)們自己去寫一下測試一下卦尊。如果只要看就都可以記住的話,那是你想的美舌厨。
NSFileManager
細(xì)心同學(xué)又發(fā)現(xiàn)了岂却,如果我的文件內(nèi)容寫錯了,怎么辦裙椭,NSFileManager幫不了躏哩。不用怕,NSFileManager 還有一個表弟##NSFileHandle 可以很好的幫助你揉燃。
NSFileHandle 又叫做文件對接器扫尺,針對的是文件內(nèi)容的讀寫操作。通過NSdata對文件內(nèi)容進(jìn)行改變炊汤。
NSFileManager 不向他表哥一樣正驻,方法不多。用到的基本有這幾個:
//對文件需要做哪一類操作
+ (nullable instancetype)fileHandleForReadingAtPath:(NSString *)path;
+ (nullable instancetype)fileHandleForWritingAtPath:(NSString *)path;
+ (nullable instancetype)fileHandleForUpdatingAtPath:(NSString *)path;
//讀取文件內(nèi)容
- (NSData *)readDataToEndOfFile;
- (NSData *)readDataOfLength:(NSUInteger)length;
//寫入內(nèi)容
- (void)writeData:(NSData *)data;
//直接偏移文件的最后
- (unsigned long long)seekToEndOfFile;
//文件偏移
- (void)seekToFileOffset:(unsigned long long)offset;
//指定文件長度抢腐,多余的數(shù)據(jù)將會被清除
- (void)truncateFileAtOffset:(unsigned long long)offset;
//關(guān)閉文件
- (void)closeFile;
//應(yīng)該是刷新同步數(shù)據(jù)使用的姑曙,不太確定。暫時沒有使用
- (void)synchronizeFile;
栗子:
//1 文件路徑
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"test.txt"];
//2 創(chuàng)建文件管理對象
NSFileManager *manager = [NSFileManager defaultManager];
//3創(chuàng)建文件
NSString *str = @"sgdhajhdg";
[manager createFileAtPath:path contents:[str dataUsingEncoding:NSUTF8StringEncoding] attributes:nil];
NSLog(@"路徑 = %@",path);
//4 文件內(nèi)容操作 創(chuàng)建文件對接器
NSFileHandle *handle = [NSFileHandle fileHandleForUpdatingAtPath:path];
//5 偏移插入位置
[handle seekToFileOffset:3];
NSData *resultData = [handle readDataToEndOfFile];
NSString *str2 = [[NSString alloc]initWithData:resultData encoding:NSUTF8StringEncoding];
NSLog(@"str2 = %@",str2);
[handle seekToFileOffset:3];
//6寫入數(shù)據(jù)
NSString *str3 = [NSString stringWithFormat:@"你好哈%@",str2];
[handle writeData:[str3 dataUsingEncoding:NSUTF8StringEncoding]];
//7 關(guān)閉文件
[handle closeFile];
可能看到第5步往下你會有一點迷糊迈倍,為什么不直接
[handle seekToFileOffset:3];
走了這一步之后伤靠,追加數(shù)據(jù)。按照這個思路啼染,最后得到的文件內(nèi)容是
ABC你好哈
而不是
ABC你好哈DEFG
各位同學(xué)可以自己測試一下宴合,看下結(jié)果。
還有一點需要特別注意迹鹅,
//5 偏移插入位置
[handle seekToFileOffset:3];
這一個偏移量需要特別注意卦洽,不是隨便寫(我這是英文字符沒有問題),如果是文件里面存儲的中文字符的話徒欣,就可以出問題逐样。你要知道,你通過偏移量得到的是NSData數(shù)據(jù)打肝,NSString獲取NSData的話脂新,通常使用NSUTF8StringEncoding去解析。UTF-8一個中文字符占3個字節(jié)粗梭,那如果你偏移的不是3的倍數(shù)的話争便,解析的數(shù)據(jù)估計就會出問題。這個建議大家去看看UTF-8的知識點断医。
Demo地址鏈接