代码改变世界

iOS的沙箱目录和文件操作

2016-04-14 22:56  樊小志  阅读(1874)  评论(0编辑  收藏  举报

一、沙箱

iOS的每一个应用程序都有自己的目录来存放数据,这个目录称为沙箱目录。沙箱目录是一种数据安全策略,它设计的原理是只能允许自己的应用访问目录,而不允许其他的应用访问,这样可以保证数据的安全,应用之间是不能共享数据的。

一些特有的应用(如通讯录)需要特定的API才能共享数据。

下面简单介绍一下,应用程序的沙箱目录,先直观的看一下演示程序的沙箱目录结构。

该应用程序的沙箱路径为:

/Users/"用户名"/Library/Developer/CoreSimulator/Devices/8DFE7883-956E-41E3-B099-18C92609E027/data/Containers/Data/Application/E82B708D-B06C-4837-BA59-74EE22CA7BE4

我们可以看到,该沙箱目录有三个子目录,分别为Documents,Library,tmp

1、Documents

该目录用于存储非常大的文件或需要非常频繁更新的数据,能够进行iTunes或iCloud备份。该目录是只有一个元素的数组,因此获取该目录位置的代码如下:

NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];

2、Library

 

该目录下面有 Preferences和Caches两个子目录,Preferences用于存放应用程序的设置数据,能够进行iTunes或iCloud备份;Caches主要用来存放应用的缓存文件,iTunes不会备份。

获取Library目录位置的代码如下:

NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];

获取Preferences目录位置的代码如下:

NSString *preferencePath = [NSSearchPathForDirectoriesInDomains(NSPreferencePanesDirectory, NSUserDomainMask, YES) lastObject];

获取Caches目录位置的代码如下:

NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];

3、tmp

该目录是用来存放临时文件的,它不能够进行iTunes或iCloud备份。用户可以访问它,获取该目录的代码如下:

NSString *tmpPath = NSTemporaryDirectory();

 二、文件操作

 1、创建文件夹

我们在documents目录下创建test文件夹

    NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    NSLog(@"document文件夹路径为%@",documentPath);
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *testPath = [documentPath stringByAppendingPathComponent:@"test"];
    BOOL isSuccess = [fileManager createDirectoryAtPath:testPath withIntermediateDirectories:YES attributes:nil error:nil];
    NSLog(@"成功创建文件夹了吗:%@",isSuccess?@"yes":@"no");

创建成功

2、创建文件

接着上面的代码,我们在test文件夹下创建文件test.txt

    NSString *txtPath = [testPath stringByAppendingPathComponent:@"test.txt"];
    BOOL isTxtSuccess = [fileManager createFileAtPath:txtPath contents:nil attributes:nil];
    NSLog(@"成功创建文件了吗:%@",isTxtSuccess?@"yes":@"no");

创建成功

可以看到test.txt还是空的,下面我们写入数据。

3、写数据到文件

    NSString *testString = @"Hello World😄";
    BOOL isWriteSuccess = [testString writeToFile:txtPath atomically:YES encoding:NSUTF8StringEncoding error:nil];
    NSLog(@"成功写入数据了吗:%@",isWriteSuccess?@"yes":@"no");

写入成功

4、读取文件

下面我们读取我们刚刚创建的test.txt文件的内容

    NSString *readString = [NSString stringWithContentsOfFile:txtPath encoding:NSUTF8StringEncoding error:nil];
    NSLog(@"读取到的文件内容为%@",readString);

成功读取

5、删除文件

    BOOL isDeleteSuccess = [fileManager removeItemAtPath:txtPath error:nil];
    NSLog(@"成功删除文件了吗:%@",isDeleteSuccess?@"yes":@"no");

删除成功

 6、计算路径下文件的总大小

+(float)sizeWithFilePath:(NSString *)path
{
    NSFileManager *fileManager = [NSFileManager defaultManager];
    
    BOOL isDirectory = NO;
    /*
     下面方法返回两个参数
     isExist:该路径是否存在
     isDirectory:该路径下是否是文件夹
     */
    BOOL isExist = [fileManager fileExistsAtPath:path isDirectory:&isDirectory];
    
    if (!isExist)
    {
        return 0;
    }
    //如果是文件夹则遍历出文件
    if (isDirectory)
    {
        //该方法能获得这个文件夹下面的所有子路径(直接/间接子路径)
        NSArray *subpaths = [fileManager subpathsAtPath:path];
        float totalSize = 0;
        for (NSString *subpath in subpaths)
        {
            NSString *fullsubpath = [path stringByAppendingPathComponent:subpath];
            //判断子路径下是否是文件夹
            BOOL isDir = NO;
            [fileManager fileExistsAtPath:fullsubpath isDirectory:&isDir];
            //子路径下是文件则计算大小
            if (!isDir)
            {
                NSDictionary *attributes = [fileManager attributesOfItemAtPath:fullsubpath error:nil];
                //得到的结果是以B为单位的,除以1024 * 1024  转换为MB
                totalSize += [attributes[NSFileSize] floatValue];
            }
        }
        NSString *sizeString = [NSString stringWithFormat:@"%.2fMB",totalSize / (1024 * 1024.0)];
        NSLog(@"路径%@下文件大小为%@",path,sizeString);
        return totalSize / (1024 * 1024.0);
    }
    else
    {
        NSDictionary *attributes = [fileManager attributesOfItemAtPath:path error:nil];
        NSLog(@"路径%@下文件大小为%f",path,[attributes[NSFileSize] floatValue] / (1024 * 1024.0));
        return [attributes[NSFileSize] floatValue] / (1024 * 1024.0);
    }
}

7、删除路径下的所有文件

+(void)cleanFileWithFilePath:(NSString *)path
{
//    NSLog(@"清除之前文件大小为%.2fMB",[FZYFileManager sizeWithFilePath:path]);
    NSFileManager *fileManager = [NSFileManager defaultManager];
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(globalQueue, ^{
        
        NSArray *subpaths = [fileManager subpathsAtPath:path];
        
        for (NSString *subPath in subpaths)
        {
            NSError *error;
            NSString *fullPath = [path stringByAppendingPathComponent:subPath];
            if ([fileManager fileExistsAtPath:fullPath])
            {
                [fileManager removeItemAtPath:fullPath error:&error];
            }
        }
        
//        NSLog(@"清除之后文件大小为%.2fMB",[FZYFileManager sizeWithFilePath:path]);
        dispatch_sync(dispatch_get_main_queue(), ^{
//            [FZYFileManager cleanSuccess];
        });
        
    });
}

点击这里可以下载相关代码