首页 > 代码库 > (转载)OC学习篇之---文件的操作

(转载)OC学习篇之---文件的操作

前一篇文章中我们讲到了OC中的归档和解档操作,今天我们来介绍OC中文件操作,在之前的文章中,已经接触到了文件的创建了,但是那不是很具体和详细,这篇文章我们就来仔细看一下OC中是如何操作文件的:

 

第一、首先来看一下本身NSString类给我们提供了哪些可以操作文件路径名的方法

 1 //   2 //  main.m   3 //  37_FilePathHandle   4 //   5 //  Created by jiangwei on 14-10-13.   6 //  Copyright (c) 2014年 jiangwei. All rights reserved.   7 //   8    9 #import <Foundation/Foundation.h>  10   11 int main(int argc, const charchar * argv[]) {  12     @autoreleasepool {  13           14         //演示路径  15         NSString *path = @"/Users/jiangwei/file.text";  16           17         //1.返回路径的组成部分  18         NSArray *array = [path pathComponents];  19         NSLog(@"%@",array);  20           21         //2.返回路径最后组成部分  22         NSString *str = [path lastPathComponent];  23         NSLog(@"%@",str);  24           25         //3.在原有的路径后面追加子目录  26         //这种方式有一点不好,就是需要添加/  27         [path stringByAppendingString:@"/appFile.text"];  28         //不需要添加/  29         [path stringByAppendingPathComponent:@"appFile.text"];  30           31         //4.删除最后的组成部分  32         str = [path stringByDeletingLastPathComponent];  33         //删除扩展名(.text被删除了)  34         str = [path stringByDeletingPathExtension];  35           36         //5.获取扩展名  37         str = [path pathExtension];  38           39         //6.添加扩展名  40         [path stringByAppendingPathExtension:@".jpg"];  41           42     }  43     return 0;  44 } 

在Java中,我们知道,当我们去操作一个文件的时候,最开始的时候肯定要去构建一个路径,这个路径一般都是String类型的,我们需要定义不同的路径和文件名,OC中也不例外,不过OC中的NSString类在这方面做的可能会更好,下面依次来看一下他的方法:

1、将路径进行分割

1 //演示路径  2 NSString *path = @"/Users/jiangwei/file.text";  3   4 //1.返回路径的组成部分  5 NSArray *array = [path pathComponents];  6 NSLog(@"%@",array);  

运行结果:

技术分享
返回的一个数组,将路径分割了,但是需要注意的是,第一个是"/",这个也算是路径的一部分。

2、返回路径的最后组成部分

1 //2.返回路径最后组成部分  2 NSString *str = [path lastPathComponent];  3 NSLog(@"%@",str);

运行结果:

技术分享
这个直接返回路径的最后一部分,这个如果放在Java中,我们可能需要用到String类的字符串分割技术了,没有这里的方便

3、添加子目录/子文件

1 //3.在原有的路径后面追加子目录  2 //这种方式有一点不好,就是需要添加/  3 //演示路径  4 str = [path stringByAppendingString:@"/appFile.text"];  5 NSLog(@"%@",str);  6 //不需要添加/  7 str = [path stringByAppendingPathComponent:@"appFile.text"];  8 NSLog(@"%@",str);

这里其实有两种方式可以添加,第一种是直接使用拼接字符串的方式,但是需要手动的添加"/",第二种方式是NSString提供的,不需要手动的添加"/"

运行结果:

技术分享

4、删除最后面的部分和后缀名

1 //4.删除最后的组成部分  2 str = [path stringByDeletingLastPathComponent];  3 NSLog(@"%@",str);  4 //删除扩展名(.text被删除了)  5 str = [path stringByDeletingPathExtension];  6 NSLog(@"%@",str); 

运行结果:

技术分享

5、获取扩展名

1 //5.获取扩展名  2 str = [path pathExtension];  3 NSLog(@"%@",str); 

运行结果:

技术分享

6、添加扩展名

1 //6.添加扩展名  2 str = [path stringByAppendingPathExtension:@"jpg"];  3 NSLog(@"%@",str); 
 

运行结果:

技术分享

上面就是总结了NSString类中操作文件路径的一些方法,其实这些操作如果放在Java中做的话,就是需要使用String的分割,拼接等技术了。这里看到OC给我们提供了便捷

 

第二、在来看一下操作文件之前需要了解的一个对象:NSData

这个类的作用就是将我们写入到文件中的数据进行编码和解码操作:

 1 //   2 //  main.m   3 //  38_NSData   4 //   5 //  Created by jiangwei on 14-10-13.   6 //  Copyright (c) 2014年 jiangwei. All rights reserved.   7 //   8    9 #import <Foundation/Foundation.h>  10   11 //NSData类型  12 //是一种存储形式  13 int main(int argc, const charchar * argv[]) {  14     @autoreleasepool {  15         //存储是有编码方式的,编程字节码  16         //相当于Java中的解码和编码  17         NSString *s = @"tsdfsdfsdfsdf";  18         NSData *data =http://www.mamicode.com/ [s dataUsingEncoding:NSUTF8StringEncoding];  19         s = [[NSString alloc] initWithData:data encoding:(NSUTF8StringEncoding)];  20           21         //可变对象 NSMutableData 可以追加数据  22     }  23     return 0;  24 } 

这个和Java中String直接在构造的时候就可以进行编码和解码了,这里需要使用中间类NSData,当然这个类是不可变的,如果想追加内容的话,需要使用NSMutableData类

 

第三、说完了NSData这个中间类,下面来正式说文件的操作了

但是这里对文件的操作,我们放到IOS平台去操作,因为我们后面也是会介绍IOS中文件的操作,所以就直接在这里说了,当然这里的知识会有点冲突,但是我们不关心IOS中的其他技术,只看他的文件操作:

1、沙盒文件

在IOS中,每个应用程序都是一个沙盒,他们有自己的文件目录,这个目录对其他程序是不可见的,和Android中的/data/data/包名/中的内容差不多,当然IOS中的沙盒目录有三种:

Documents:存放长期使用的文件(一般存放目录)

Library:系统存放文件

tmp:临时文件,app重启时,该目录下得文件清空

下面来看一个简单的例子吧:

 1 //   2 //  main.m   3 //  36_SandBoxFile   4 //   5 //  Created by jiangwei on 14-10-13.   6 //  Copyright (c) 2014年 jiangwei. All rights reserved.   7 //   8    9 #import <UIKit/UIKit.h>  10 #import "AppDelegate.h"  11   12 int main(int argc, charchar * argv[]) {  13     @autoreleasepool {  14         //获取沙盒目录  15         //默认有三个文件夹  16         //Documents:存放长期使用的文件(一般存放目录)  17         //Library:系统存放文件  18         //tmp:临时文件,app重启时,该目录下得文件清空  19           20         //第一种获取方式,我们得到Home目录之后,手动的去拼接Document/Library  21         NSString *homePath = NSHomeDirectory();  22         NSLog(@"沙盒目录:%@",homePath);  23           24         //第二种方式,直接使用Api获取  25         //NSDocumentDirectory:Documents文件夹  26         //NSLibraryDirectory:Library文件夹  27         NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);  28         NSLog(@"%@",array);  29           30         NSArray *array1 = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);  31         NSLog(@"%@",array1);  32           33         return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));  34     }  35 }  

创建IOS项目和OC差不多:

技术分享

后续的操作就一样了,创建完之后的项目结构:

技术分享
我们在main.m文件中写我们的代码就可以了。

下面来看代码:

1 //第一种获取方式,我们得到Home目录之后,手动的去拼接Document/Library  2 NSString *homePath = NSHomeDirectory();  3 NSLog(@"沙盒目录:%@",homePath);
 

获取沙盒的home目录,然后我们可以操作在其下面创建子目录了。

这里有两种方式去创建Document等目录,一种是我们用上面NSString类提供的方法去手动拼接目录,还有一种是用系统给我们提供的方法,这两种都是可以的。

1 //第二种方式,直接使用Api获取  2 //NSDocumentDirectory:Documents文件夹  3 //NSLibraryDirectory:Library文件夹  4 NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);  5 NSLog(@"%@",array);  6           7 NSArray *array1 = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);  8 NSLog(@"%@",array1);  

看一下运行结果:

技术分享

 

第四、了解了程序的沙盒目录,下面继续来看一下操作文件的两个类

一、NSFileManager

这个类的主要功能是对文件进行操作:创建,复制,剪切,删除等。

看代码:

 1 //   2 //  main.m   3 //  39_NSFileManager   4 //   5 //  Created by jiangwei on 14-10-13.   6 //  Copyright (c) 2014年 jiangwei. All rights reserved.   7 //   8    9 #import <UIKit/UIKit.h>  10 #import "AppDelegate.h"  11   12 //NSFileManager:对文件进行操作的,包括复制,粘贴,删除,剪切等操作  13 int main(int argc, charchar * argv[]) {  14     @autoreleasepool {  15           16         //------------------创建文件/文件夹  17         //获取沙盒目录  18         NSString *homePath = NSHomeDirectory();  19         //在沙盒目录中创建一个文件file.text  20         NSString *filePath = [homePath stringByAppendingPathComponent:@"Documents/file.text"];  21         //NSFileManager是单利模式,所以不能使用alloc+init创建  22         NSFileManager *manager = [NSFileManager defaultManager];  23         NSString *str = @"无线互联";  24         NSData *data =http://www.mamicode.com/ [str dataUsingEncoding:NSUTF8StringEncoding];  25         //参数:文件路径、文件内容、文件的属性  26         BOOL sucess = [manager createFileAtPath:filePath contents:data attributes:nil];  27         if(sucess){  28             NSLog(@"文件创建成功");  29         }else{  30             NSLog(@"文件创建失败");  31         }  32           33         //创建文件夹  34         NSString *filePaths = [homePath stringByAppendingPathComponent:@"Documents/file"];  35         NSError *error;  36         //需要传递一个创建失败的指针对象,记录创建失败的信息  37         BOOL success1 = [manager createDirectoryAtPath:filePaths withIntermediateDirectories:YES attributes:nil error:&error];  38         if(!success1){  39             NSLog(@"创建成功");  40         }else{  41             NSLog(@"创建失败");  42         }  43           44           45         //--------------------读取文件  46         //根据路径读取文件内容  47         NSData *datas = [manager contentsAtPath:filePath];  48         NSString *s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];  49         NSLog(@"%@",s);  50           51           52         //--------------------移动文件/剪切文件  53         //NSFileManager中没有提供重命名的方法,所以我们可以借助移动的api进行操作  54         //把filePath移动到targetPath目录中  55         NSString *targetPath = [homePath stringByAppendingPathComponent:@"Documents/file/file2.text"];  56         BOOL sucess2 = [manager moveItemAtPath:filePath toPath:targetPath error:nil];  57         if(sucess2) {  58             NSLog(@"移动成功");  59         }else{  60             NSLog(@"移动失败");  61         }  62           63           64         //--------------------复制文件  65         BOOL sucess3 = [manager copyItemAtPath:filePath toPath:targetPath error:nil];  66         if(sucess3){  67             //复制成功  68         }else{  69             //复制失败  70         }  71           72           73         //--------------------删除文件  74         //删除之前需要判断这个文件是否存在  75         BOOL isExist = [manager fileExistsAtPath:filePath];//判断文件是否存在  76         if(isExist){  77             BOOL sucess4 = [manager removeItemAtPath:filePath error:nil];  78             if(sucess4){  79                 //删除成功  80             }else{  81                 //删除失败  82             }  83         }  84           85           86         //--------------------获取文件的属性  87         NSDictionary *dic = [manager attributesOfItemAtPath:filePath error:nil];  88         NSLog(@"%@",dic);//通过打印我们就可以查看文件属性的一些key  89           90         return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));  91     }  92 } 

1、创建文件

 1 //------------------创建文件/文件夹   2 //获取沙盒目录   3 NSString *homePath = NSHomeDirectory();   4 //在沙盒目录中创建一个文件file.text   5 NSString *filePath = [homePath stringByAppendingPathComponent:@"Documents/file.text"];   6 //NSFileManager是单利模式,所以不能使用alloc+init创建   7 NSFileManager *manager = [NSFileManager defaultManager];   8 NSString *str = @"无线互联";   9 NSData *data =http://www.mamicode.com/ [str dataUsingEncoding:NSUTF8StringEncoding];  10 //参数:文件路径、文件内容、文件的属性  11 BOOL sucess = [manager createFileAtPath:filePath contents:data attributes:nil];  12 if(sucess){  13     NSLog(@"文件创建成功");  14 }else{  15     NSLog(@"文件创建失败");  16 } 
 

NSFileManager内部使用了单例模式,这个后面会说到OC中得单例模式,然后就是构建一个NSData类,最后使用createFileAtPath方法创建文件,不过最后的attributes参数一般是用来给这个文件定义一些属性的,当然文件本身也是有很多默认的属性,比如文件的大小,文件的创建日期等,我们也可以自己在追加一些属性。

2、创建文件夹

 1 //创建文件夹   2 NSString *filePaths = [homePath stringByAppendingPathComponent:@"Documents/file"];   3 NSError *error;   4 //需要传递一个创建失败的指针对象,记录创建失败的信息   5 BOOL success1 = [manager createDirectoryAtPath:filePaths withIntermediateDirectories:YES attributes:nil error:&error];   6 if(!success1){   7     NSLog(@"创建成功");   8 }else{   9     NSLog(@"创建失败");  10 }  

从这两个操作看出来,他和Java中的File类很相似的

3、读取文件

1 //--------------------读取文件  2 //根据路径读取文件内容  3 NSData *datas = [manager contentsAtPath:filePath];  4 NSString *s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];  5 NSLog(@"%@",s);  

4、剪切文件

 1 //--------------------移动文件/剪切文件   2 //NSFileManager中没有提供重命名的方法,所以我们可以借助移动的api进行操作   3 //把filePath移动到targetPath目录中   4 NSString *targetPath = [homePath stringByAppendingPathComponent:@"Documents/file/file2.text"];   5 BOOL sucess2 = [manager moveItemAtPath:filePath toPath:targetPath error:nil];   6 if(sucess2) {   7     NSLog(@"移动成功");   8 }else{   9     NSLog(@"移动失败");  10 }  

这里有两个参数:一个是需要移动文件的路径,和需要移动到哪的路径

5、复制文件

1 //--------------------复制文件  2 BOOL sucess3 = [manager copyItemAtPath:filePath toPath:targetPath error:nil];  3 if(sucess3){  4     //复制成功  5 }else{  6     //复制失败  7 }  

6、删除文件

 1 //--------------------删除文件   2 //删除之前需要判断这个文件是否存在   3 BOOL isExist = [manager fileExistsAtPath:filePath];//判断文件是否存在   4 if(isExist){   5     BOOL sucess4 = [manager removeItemAtPath:filePath error:nil];   6     if(sucess4){   7         //删除成功   8     }else{   9         //删除失败  10     }  11 }  

7、操作文件的属性

1 //--------------------获取文件的属性  2 NSDictionary *dic = [manager attributesOfItemAtPath:filePath error:nil];  3 NSLog(@"%@",dic);//通过打印我们就可以查看文件属性的一些key 

属性一般是NSDictionary

 

二、NSFileHandle

这个类主要是对文件进行读写操作的。

看代码:

 1 //   2 //  main.m   3 //  40_NSFileHandle   4 //   5 //  Created by jiangwei on 14-10-13.   6 //  Copyright (c) 2014年 jiangwei. All rights reserved.   7 //   8    9 #import <UIKit/UIKit.h>  10 #import "AppDelegate.h"  11   12 //写文件,我们之前使用各种数据结构来存储数据:NSString,NSData,NSDictionary,NSArray等,他们都是有一个writeToFile方法用来写文件的  13   14 //纯文本:没有任何格式的数据  15 //非纯文本:有修饰的数据(字体大小,字体颜色等)  16   17 //数组只能将如下类型写入文件,如果包含其他对象,将写入失败:NSNumber,NSString,NSData,NSDate,NSArray,NSDictionary  18 //数组、字典写入的文件叫做属性文件,可以使用xcode进行编辑  19 int main(int argc, charchar * argv[]) {  20     @autoreleasepool {  21           22         //1.-------------------字符串读写文件  23         NSString *str = @"无线互联";  24         NSString *homePath = NSHomeDirectory();  25         NSString *filePath = [homePath stringByAppendingPathComponent:@"Documents/file.text"];  26         //现在有这样的场景,第一次把字符串写入到文件中,当我们修改字符串之后,再次写入的时候,但是可能会写入失败  27         //但是之前的内容也有可能丢失,因为每次在写入新的内容的时候,会剪切之前的内容,所以这里就有可能新的没有写  28         //成功,旧的文件也丢失了  29         //所以这时候atomically参数:  30         //YES:会将新内容先写入到一个缓存文件中,如果写入缓存成功之后,这时候就将这个缓存文件替换旧文件,这样就很安全了  31         BOOL sucess = [str writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];  32         if(sucess){  33             //写入成功  34         }else{  35             //写入失败  36         }  37         //读取文件内容到字符串中  38         //类方法  39         NSString *str1 = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];  40         //构造方法  41         //str1 = [[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];  42         NSLog(@"%@",str1);  43           44           45         //2.--------------------NSData读写  46         //创建NSData的同时读取文件中的内容  47         NSData *data =http://www.mamicode.com/ [[NSData alloc] initWithContentsOfFile:filePath];  48         //NSData转化成NSString  49         NSString *s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];  50         NSLog(@"%@",s);  51           52         //写文件  53         BOOL sucess1 = [data writeToFile:filePath atomically:YES];  54         if(sucess1){  55             //写入成功  56         }else{  57             //写入失败  58         }  59           60           61         //3.--------------------NSArray读写文件  62         NSArray *array = @[@"zhangsan",@"lisi"];  63         //属性文件一般后缀名为.plist  64         NSString *filePaths = [homePath stringByAppendingPathComponent:@"Documents/array.plist"];  65         BOOL sucess2 = [array writeToFile:filePaths atomically:YES];  66         if(sucess2){  67             //写入成功  68         }else{  69             //写入失败  70         }  71         //读文件  72         NSArray *arrays = [[NSArray alloc] initWithContentsOfFile:filePath];  73         NSLog(@"%@",arrays);  74           75           76         //4.---------------------NSDictionary读写文件  77         NSDictionary *dic = @{@"zhang":@"zhangsan",@"li":@"lisi"};  78         BOOL sucess3 = [dic writeToFile:filePath atomically:YES];  79         if(sucess3){  80             //写入成功  81         }else{  82             //写入失败  83         }  84           85         //读文件  86         dic = [[NSDictionary alloc] initWithContentsOfFile:filePath];  87         NSLog(@"%@",dic);  88           89           90         return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));  91     }  92 }

这个类就和Java中的FileInputStream/FileOutputStream类似了,其实我们在之前看到归档和解档操作的时候,那就是相当于写文件和读文件操作了。

1、字符串直接写入文件

 1 //1.-------------------字符串读写文件   2 NSString *str = @"无线互联";   3 NSString *homePath = NSHomeDirectory();   4 NSString *filePath = [homePath stringByAppendingPathComponent:@"Documents/file.text"];   5 //现在有这样的场景,第一次把字符串写入到文件中,当我们修改字符串之后,再次写入的时候,但是可能会写入失败   6 //但是之前的内容也有可能丢失,因为每次在写入新的内容的时候,会剪切之前的内容,所以这里就有可能新的没有写   7 //成功,旧的文件也丢失了   8 //所以这时候atomically参数:   9 //YES:会将新内容先写入到一个缓存文件中,如果写入缓存成功之后,这时候就将这个缓存文件替换旧文件,这样就很安全了  10 BOOL sucess = [str writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];  11 if(sucess){  12     //写入成功  13 }else{  14     //写入失败  15 }  16 //读取文件内容到字符串中  17 //类方法  18 NSString *str1 = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];  19 //构造方法  20 //str1 = [[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];  21 NSLog(@"%@",str1); 
 

我们使用拼接的方式创建Documents目录中的file.text文件,然后将字符串内容写入到其中。

writeToFile方法进行写入:

其实OC中的各种数据结构都有这个方法的:NSString,NSData,NSArray,NSSet,NSDirctionary等。

这里有两点要注意的:

1)数组只能将如下类型写入文件,如果包含其他对象,将写入失败:NSNumber,NSString,NSData,NSDate,NSArray,NSDictionary

数组、字典写入的文件叫做属性文件,可以使用xcode进行编辑。

技术分享