首页 > 代码库 > IOS-沙盒机制(二 文件读写)

IOS-沙盒机制(二 文件读写)

一 目录说明

   如下图所示,一个沙盒中典型存在下面的目录和文件
                    

各个目录及文件说明:
1.Documents      您应该将所有的应用程序数据文件写入到这个目录下,这个目录用于存储用户数据或其它应该定期备份的信息。
2.AppName.app   这是应用程序的程序包目录,包含应用程序的本身。由于应用程序必须经过签名,所以您在运行时不能对这目录中的内容进行修改,否则可能会使应用程序无法启动。
3.Library              这个目录下有两个子目录:Caches 和 Preferences
    Preferences      包含应用程序的偏好设置文件。您不应该直接创建偏好设置文件,而是应该使用NSUserDefaults类来取得和设置应用程序的偏好
     Caches 目录用于存放应用程序专用的支持文件,保存应用程序再次启动过程中需要的信息。
4.tmp                  这个目录用于存放临时文件,保存应用程序再次启动过程中不需要的信息。

注意:1.iTunes在与iPhone同步时,备份所有的Documents和Library文件。
          2.iPhone在重启时,会丢弃所有的tmp文件。

二 沙盒中文件夹和文件操作

实例代码一:列出相应的目录
- (void) fileOperation
{
    //沙盒所在的根目录
    NSString *homeDirectory = NSHomeDirectory();
    NSLog(@"path:%@", homeDirectory);
    
    //应用程序路径
    NSString*appPath  = [[NSBundle mainBundleresourcePath];
    NSLog(@"path:%@", appPath);

    //document目录
    NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectoryNSUserDomainMaskYES);
    NSString *documentPaths = [docPaths objectAtIndex:0];
    NSLog(@"path:%@", documentPaths);
   
    //Cache目录
    NSArray *cacPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectoryNSUserDomainMaskYES);
    NSString *cachePath = [cacPaths objectAtIndex:0];
    NSLog(@"%@", cachePath);
   
    //获取Library目录
    NSArray *libPaths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectoryNSUserDomainMaskYES);
    NSString *libraryPath = [libPaths objectAtIndex:0];
    NSLog(@"%@", libraryPath);
   
    //获取Tmp目录
    NSString *tmpDir = NSTemporaryDirectory();
    NSLog(@"%@", tmpDir);
   
   
}
输出结果:
2014-04-23 14:55:35.621 ZZFile[12523:70b] path:/Users/XXXXXX/Library/Application Support/iPhone Simulator/7.0.3/Applications/9170019F-379C-42C3-96E2-848CE9268FEF
2014-04-23 14:55:35.623 ZZFile[12523:70b] path:/Users/XXXXXX/Library/Application Support/iPhone Simulator/7.0.3/Applications/9170019F-379C-42C3-96E2-848CE9268FEF/ZZFile.app
2014-04-23 14:55:35.624 ZZFile[12523:70b] path:/Users/XXXXXX/Library/Application Support/iPhone Simulator/7.0.3/Applications/9170019F-379C-42C3-96E2-848CE9268FEF/Documents
2014-04-23 14:55:35.626 ZZFile[12523:70b] /Users/XXXXXX/Library/Application Support/iPhone Simulator/7.0.3/Applications/9170019F-379C-42C3-96E2-848CE9268FEF/Library/Caches
2014-04-23 14:55:35.631 ZZFile[12523:70b] /Users/XXXXXX/Library/Application Support/iPhone Simulator/7.0.3/Applications/9170019F-379C-42C3-96E2-848CE9268FEF/Library
2014-04-23 14:55:35.632 ZZFile[12523:70b] /Users/XXXXXX/Library/Application Support/iPhone Simulator/7.0.3/Applications/9170019F-379C-42C3-96E2-848CE9268FEF/tmp/

实例代码二:文件读写
- (void) WRFile
{
    //写入数据
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectoryNSUserDomainMaskYES);
    NSString *docDir = [paths objectAtIndex:0];
    if (!docDir)
    {
        NSLog(@"Documents 目录未找到");
    }
    NSArray *array = [[NSArray allocinitWithObjects:@"Hebie",@"BJUT",nil];
    NSString *filePath = [docDir stringByAppendingPathComponent:@"zz.text"];
    [array writeToFile:filePath atomically:YES];

    
    //读取数据
    // NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    // NSString *docDir = [paths objectAtIndex:0];
   //  NSString *filePath = [docDir stringByAppendingPathComponent:@"testFile.txt"];
    NSArray *result = [[NSArray alloc]initWithContentsOfFile:filePath];
    NSLog(@"%@", result);
}
- (void) userDefalut
{
    NSUserDefaults *defalut =  [NSUserDefaults standardUserDefaults];
    [defalut setObject:@"ZZBJUT" forKey:@"name"];
    [defalut setObject:[NSNumber numberWithInteger:25forKey:@"age"];
    [defalut synchronize];
    
    defalut = nil;
    
    defalut =  [NSUserDefaults standardUserDefaults];
    NSString *name = [defalut  objectForKey:@"name"];
    NSInteger age  = [[defalut objectForKey:@"age"integerValue];
    NSLog(@"name:%@  age:%d",name ,age);
    
}
输出结果:
2014-04-23 14:01:11.559 ZZFile[12104:70b] (
    Hebie,
    BJUT
)
2014-04-23 14:01:11.855 ZZFile[12104:70b] name:ZZBJUT  age:25

沙盒中的Documents目录中多了一个zz.text
另外在Library的Preferences目录中多了一个 com.qiniudn.zhangzhe.ZZFile.plist文件
如下图所示:
                           

打开com.qiniudn.zhangzhe.ZZFile.plist文件里面是我们用NSUserDefault保存的数据。
               

打开zz.txt文件
<?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>Hebie</string>
     <string>BJUT</string>
</array>
</plist> 
可以看到文件中的数据使用属性列表的格式进行存储

使用如下代码删除文件:
//删除文件
if ([[NSFileManager defaultManagerfileExistsAtPath:finalLocation])
{
   retVal = [[NSFileManager defaultManagerremoveItemAtPath:finalLocation error:NULL]; 
   NSLog(@"delete file:%@",finalLocation);
}

实例代码三:文件夹操作
- (void)createFolder:(NSString *)createDir
{
    BOOL isDir = NO;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL existed = [fileManager fileExistsAtPath:createDir isDirectory:&isDir];
    if ( !(isDir == YES && existed == YES) )
    {
          [fileManager createDirectoryAtPath:createDir withIntermediateDirectories:YES attributes:nil error:nil];
    }
}
- (void) folderOperation
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectoryNSUserDomainMaskYES);
    NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
    NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"first"];
    [self createFolder:dataPath];
   
    dataPath = [dataPath stringByAppendingPathComponent:@"secode"];
    [self createFolder:dataPath];
    
    //创建文件
    NSString *testPath = [dataPath stringByAppendingPathComponent:@"zz.txt"];
    NSString *string = @"ZZBJUT 写入文件";
    NSFileManager *fileManager = [NSFileManager defaultManager];
    [fileManager createFileAtPath:testPath
                         contents:[string dataUsingEncoding:NSUTF8StringEncoding]
                       attributes:nil];
    dataPath  = [dataPath stringByAppendingPathComponent:@"third"];
    [self createFolder:dataPath];
}

沙盒中的内容如下,可以看到在document目录中创建/first/second/third目录,并且在
seconde中创建了一个zz.text文件。
                 


实例代码四:拷贝app目录中的文件到Document中
- (void) copyBundleFileToDocument
{
    NSString *flieName = @"apple.jpg";
    NSString *fileToCopy = [[NSBundle mainBundlepathForResource:@"apple.jpg" ofType:nil];
   
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectoryNSUserDomainMaskYES);
    NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
    NSString *dataPath = [documentsDirectory stringByAppendingString:@"/first/second/third"];
    NSString * finalLocation = [dataPath stringByAppendingPathComponent:flieName];
   
    BOOL retVal = YES// If the file already exists, we‘ll return success…
   
    if (![[NSFileManager defaultManagerfileExistsAtPath:finalLocation])
    {
        retVal = [[NSFileManager defaultManagercopyItemAtPath:fileToCopy
                                                         toPath:finalLocation
                                                          error:NULL];
        NSLog(@"copy done!");
        NSLog(@"souce:%@",fileToCopy);
        NSLog(@"destination:%@",finalLocation);
    }
}
输出结果:
2014-04-23 14:15:35.262 ZZFile[12218:70b] copy done!
2014-04-23 14:15:35.265 ZZFile[12218:70b] souce:/Users/XXXXXX/Library/Application Support/iPhone Simulator/7.0.3/Applications/9170019F-379C-42C3-96E2-848CE9268FEF/ZZFile.app/apple.jpg
2014-04-23 14:15:35.266 ZZFile[12218:70b] destination:/Users/XXXXXX/Library/Application Support/iPhone Simulator/7.0.3/Applications/9170019F-379C-42C3-96E2-848CE9268FEF/Documents/first/second/third/apple.jpg

如下图所示我们将app目录中的apple.jgp文件拷贝到了Documents的third文件夹中
                                           

                    


注意:
     NSBundle是一个目录,其中包含了程序使用到的资源,包含了如图像、声音、编译好的代码、nib文件(用户也会把bundle称为plug-in)等。对应bundle,cocoa提供了类NSBundle.
     Bundle其实是一种对应用程序的打包方式,就像java中的jar文件一样。NSBundle是对bundle的一种抽象表示,使用它可以便捷的访问应用程序中的资源。
      上面代码中用NSBundle获取程序里的一张图片apple.jpg,根据输出的结果图片的路径为:
/Users/XXXXXX/Library/Application Support/iPhone Simulator/7.0.3/Applications/9170019F-379C-42C3-96E2-848CE9268FEF/ZZFile.app/apple.jpg

实例代码五:列出目录内容
- (void) listFile
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectoryNSUserDomainMaskYES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSFileManager *fileManage = [NSFileManager defaultManager];
    NSArray *file = [fileManage subpathsOfDirectoryAtPath: documentsDirectory error:nil];
    NSLog(@"%@",file);
}

输出内容:
2014-04-23 14:31:24.881 ZZFile[12334:70b] (
    ".DS_Store",
    first,
    "first/.DS_Store",
    "first/second",
    "first/second/.DS_Store",
    "first/second/third",
    "first/second/third/apple.jpg",
    "first/second/zz.txt",
    "zz.text"
)
实例代码六:混合数据的读写
- (void) writeMixData
{
    NSString * fileName = @"mixtypedata.txt";
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectoryNSUserDomainMaskYES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    //获取文件路径
    NSString *path = [documentsDirectory stringByAppendingPathComponent:fileName];
  
    //待写入的数据
    NSString *temp = @"Hello world!";
    int dataInt = 1234;
    float dataFloat = 3.14f;
   
    //创建数据缓冲
    NSMutableData *writer = [[NSMutableData allocinit];
    //将字符串添加到缓冲中
    [writer appendData:[temp dataUsingEncoding:NSUTF8StringEncoding]];
    //将其他数据添加到缓冲中
    [writer appendBytes:&dataInt length:sizeof(int)];
    [writer appendBytes:&dataFloat length:sizeof(float)];
    //将缓冲的数据写入到文件中 
    [writer writeToFile:path atomically:YES];
   
    //[self readMixData];
}
- (void) readMixData
{
    NSString * fileName = @"mixtypedata.txt";
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectoryNSUserDomainMaskYES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    //获取文件路径
    NSString *path = [documentsDirectory stringByAppendingPathComponent:fileName];
 
   
    //读取数据:
    int intData;
    float floatData =http://www.mamicode.com/ 0.0;
    NSString *stringData;
   
    NSData *reader = [NSData dataWithContentsOfFile:path];
    stringData = http://www.mamicode.com/[[NSString allocinitWithData:
                  [reader subdataWithRange:NSMakeRange(0, [@"Hello world!" length])]
                                       encoding:NSUTF8StringEncoding];
   
    [reader getBytes:&intData range:NSMakeRange([@"Hello world!"length], sizeof(int))];
    [reader getBytes:&floatData range:NSMakeRange([@"Hello world!" length] + sizeof(int), sizeof(float))];
    NSLog(@"stringData:%@ intData:%d floatData:%f", stringData, intData, floatData);
}

输出结果
2014-04-23 14:44:53.820 ZZFile[12452:70b] stringData:Hello world! intData:1234 floatData:3.140000
注意:当字符串中有中文的时候会出现乱码,因为[temp length]算长度是,把中文算成一位了,出来的结果有误。

三   文件操作封装
     封装类ZZFile   
          头文件ZZFile.h 如下:
         @interface ZZFile : NSObject
          //Get Home/Bundle/Document/Library/Cache/Temp  Directory
          + (NSString*) HomeDirectory;
          + (NSString*) BundleDirectory;
          + (NSString*) DocumentDirectory;
          + (NSString*) LibraryDirectory;
          + (NSString*) LibraryCacheDirectory;
          + (NSString*) TempDirectory;
          
          //File Path.
          + (NSString *) DocumentFilePath:(NSString *) fileName;
          + (BOOL)  FileIsExist:(NSString*) fileName;
          + (BOOL)  DocumentFileIsExist:(NSString*) fileName;
          
          //File Operation.
          + (BOOL)  WriteObject:(id) object filePath:(NSString*) fileName;
          + (BOOL)  WriteObject:(id) object DocumentFilePath:(NSString *)fileName;
          + (BOOL)  removeFileAtPath:(NSString*) fileName;
          + (BOOL)  removeDocumentFileAtPath:(NSString *)fileName;
          + (BOOL)  RenameDocumentFile:(NSString*) oldName forName:(NSString*) newName;
          + (BOOL)  CopyDocumentFileFrom:(NSString*) source To:(NSString*)destination;

          //Folder Operation.
          + (BOOL)  CreateDocumentFolder:(NSString*) folderName;
          + (BOOL)  RemoveDocumentFolder:(NSString*) folderName;
          + (BOOL)  RenameDocumentFolder:(NSString*) oldName forName:(NSString*) newName;
          + (BOOL)  CopyDocumentFolderFrom:(NSString*) source To:(NSString*)destination;
          + (NSArray*) TraverseDocumentFolder:(NSString*) folderName;

          //Copy Bundle file To Document
          + (BOOL)  CopyBundleFile:(NSString*) fileName ToDocument:(NSString*) documentFileName;

          //NSUserDefalut
          + (void) UserDefalutObject:(id)object forKey:(NSString*) key;
          + (id)   UserDefalutObjectForKye:(NSString*) key;
          + (void) Synchronize;
           
           //Hash File
      + (NSString *md5HashOfFileAtPath:(NSString *filePath;
      + (NSString *sha1HashOfFileAtPath:(NSString *filePath;
      + (NSString *sha512HashOfFileAtPath:(NSString *filePath;
          @end

     详见github:  https://github.com/ZhangzheBJUT/IOSProject/tree/master/FiltTool
      ZZFile.h和ZZFile.m是对文件操作的简单封装,方便文件的存取修改。