iOS 文件操作简介

栏目: IOS · 发布时间: 7年前

内容简介:级别: ★★☆☆☆标签:「iOS 文件操作」「SandBox」「QiFileManager」作者:dac_1033

级别: ★★☆☆☆

标签:「iOS 文件操作」「SandBox」「QiFileManager」

作者:dac_1033

审校:QiShare团队

在iOS开发过程中,网络出错没有返回正确数据时有发生,这时可以读取本地数据展示给用户来优化用户体验,并且在网络请求正常时及时更新这些本地数据,这些本地数据一般都存在沙盒目录的文件中,下面我们就来简单介绍一下iOS开发中的文件操作。 附:苹果官方文件系统编程指南。

一、 关于iOS文件系统

1.1 沙盒(SandBox)

iOS中每个app都有个独立、封闭、安全的目录,叫做沙盒,它一般存放着程序包文件(可执行文件)、图片、音频、视频、 plist 文件、 SQLite 数据库以及其他文件。每个app的沙盒都是独立的,应用程序之间是不可以直接互相访问的。苹果官网将沙盒结构划分为三类( Bundle ContainerData ContaineriClound Container ),如下图:

iOS 文件操作简介

上图中的沙盒结构其实是与小编的理解有出入的,具体的沙盒结构我们暂且不做研究。在开发iOS应用程序过程中,我们只能看到沙盒中的根目录及默认生成的三个文件夹 DocumentsLibraryTmp ,这些才是我们关注的重点, 关于常用目录的描述如下:

目录 描述
AppName.app 应用程序的程序包目录,包含应用程序的本身。由于应用程序必须经过签名,所以不能在运行时对这个目录中的内容进行修改,否则会导致应用程序无法启动。
Documents/ 保存应用程序的重要数据文件和用户数据文件等。用户数据基本上都放在这个位置(例如从网上下载的图片或音乐文件),该文件夹在应用程序更新时会自动备份,在连接iTunes时也可以自动同步备份其中的数据;
该目录的内容被iTunes和iCloud备份。
Library/ 这个目录下有两个子目录,可创建子文件夹。可以用来放置您希望被备份但不希望被用户看到的数据。该路径下的文件夹,除Caches以外,都会被iTunes备份;
该目录的内容被iTunes和iCloud备份
Library/Caches 保存应用程序使用时产生的支持文件和缓存文件(保存应用程序再次启动过程中需要的信息),还有日志文件最好也放在这个目录;
iTunes 不会备份该目录,并且该目录下数据可能被其他 工具 清理掉。
Library/Preferences 保存应用程序的偏好设置文件。NSUserDefaults类创建的数据和plist文件都放在这里;
该目录的内容被iTunes和iCloud备份。
Tmp/ 使用此目录可以编写在应用程序启动之间不需要保留的临时文件,您的应用程序应在不再需要时删除此目录中的文件,但是,当您的应用未运行时,系统可能会清除此目录;
iTunes或iCloud不会备份此目录下的内容。

1.2 获取沙盒目录

- (void)testSandBoxDirectory {
    
    // 获取app沙盒的根目录(home)
    NSString *homePath = NSHomeDirectory();
    NSLog(@"NSHomeDirectory: %@", homePath);
    
    // 获取temp路径
    NSString *tmp = NSTemporaryDirectory( );
    NSLog(@"NSTemporaryDirectory: %@", tmp);
    
    // 获取Document目录
    NSArray  *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docPath = [paths lastObject];
    NSLog(@"NSDocumentDirectory: %@", docPath);
    
    // 获取Library目录
    paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
    NSString *libPath = [paths lastObject];
    NSLog(@"NSLibraryDirectory: %@", libPath);
    
    // 获取Library中的Cache
    paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *cachesPath = [paths lastObject];
    NSLog(@"NSCachesDirectory: %@", cachesPath);
}
复制代码

1.3 常用的路径处理方法

系统在类 NSPathUtilities 中实现了对NSString的扩展NSString ( NSStringPathExtensions ),其中定义了很多方法专门用于处理路径:

- (NSArray *)pathComponents;
- (NSString *)lastPathComponent;
- (NSString *)stringByDeletingLastPathCpmponent;
- (NSString *)stringByAppendingPathConmponent:(NSString *)str;
- (NSString *)pathExtension;
- (NSString *)stringByDeletingPathExtension;
- (NSString *)stringByAppendingPathExtension:(NSString *)str;
复制代码

1.4 iOS工程中的NSBundle

iOS 文件操作简介

如图,我们自己在工程中创建了一个 Test.bundlebundle 是一个目录,其中包含程序会使用到的资源(如图像、声音、代码文件、 nib 文件等)。在系统中app本身和其他文件没有什么区别,app包中实际上包含了 nib 文件、编译连接过的代码和其他资源的目录,我们把app包这个目录叫做该app的 main bundle 。在iOS开发中可以使用NSBundle类来操作bundle及其中的资源。 NSBundle的官方文档描述

使用NSBundle的示例代码如下:

// 获取main bundle
NSBundle *mainBundle = [NSBundle mainBundle];
// 放在app mainBundle中的自定义Test.bundle
NSString *testBundlePath = [mainBundle pathForResource:@"Test" ofType:@"bundle"];
NSBundle *testBundle = [NSBundle bundleWithPath:testBundlePath];
    
// 获取Test.bundle中资源
NSString *resPath = [testBundle pathForResource:@"sound02" ofType:@"wav"];
NSLog(@"自定义bundle中资源的路径: %@", resPath);
    
// 直接根据目录获取资源
UIImage *img = [UIImage imageNamed:[NSString stringWithFormat:@"Test.bundle/%@", @"logo_img_02"]];
NSLog(@"自定义bundle中图片: %@", img);
复制代码

二、文件操作

2.1 文件路径及文件

// 获取沙盒根路径
+ (NSString *)getHomePath {
    
    return NSHomeDirectory();
}

// 获取tmp路径
+ (NSString *)getTmpPath {
    
    return NSTemporaryDirectory();
}

// 获取Documents路径
+ (NSString *)getDocumentsPath {
    
    NSArray *pathArr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *path = [pathArr firstObject];
    return path;
}

// 获取Library路径
+ (NSString *)getLibraryPath {
    
    NSArray *pathArr = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
    NSString *path = [pathArr firstObject];
    return path;
}

// 获取LibraryCache路径
+ (NSString *)getLibraryCachePath {
    
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *path = [paths firstObject];
    return path;
}

// 检查文件、文件夹是否存在
+ (BOOL)fileExistsAtPath:(NSString *)path isDirectory:(BOOL *)isDir {
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL exist = [fileManager fileExistsAtPath:path isDirectory:isDir];
    return exist;
}

// 创建路径
+ (void)createDirectory:(NSString *)path {
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL isDir;
    BOOL exist = [fileManager fileExistsAtPath:path isDirectory:&isDir];
    if (!isDir) {
        [fileManager removeItemAtPath:path error:nil];
        exist = NO;
    }
    if (!exist) {
        // 注:直接创建不会覆盖原文件夹
        [fileManager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
    }
}

// 创建文件
+ (NSString *)createFile:(NSString *)filePath fileName:(NSString *)fileName {
    
    // 先创建路径
    [self createDirectory:filePath];
    
    // 再创建路径上的文件
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *path = [filePath stringByAppendingPathComponent:fileName];
    BOOL isDir;
    BOOL exist = [fileManager fileExistsAtPath:path isDirectory:&isDir];
    if (isDir) {
        [fileManager removeItemAtPath:path error:nil];
        exist = NO;
    }
    if (!exist) {
        // 注:直接创建会被覆盖原文件
        [fileManager createFileAtPath:path contents:nil attributes:nil];
    }
    return path;
}

// 复制 文件or文件夹
+ (void)copyItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath {
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error;
    BOOL result = [fileManager copyItemAtPath:srcPath toPath:dstPath error:&error];
    if (!result && error) {
        NSLog(@"copyItem Err : %@", error.description);
    }
}

// 移动 文件or文件夹
+ (void)moveItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath {
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error;
    BOOL result = [fileManager moveItemAtPath:srcPath toPath:dstPath error:&error];
    if (!result && error) {
        NSLog(@"moveItem Err : %@", error.description);
    }
}

// 删除 文件or文件夹
+ (void)removeItemAtPath:(NSString *)path {
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error;
    BOOL result = [fileManager removeItemAtPath:path error:&error];
    if (!result && error) {
        NSLog(@"removeItem Err : %@", error.description);
    }
}

// 获取目录下所有内容
+ (NSArray *)getContentsOfDirectoryAtPath:(NSString *)docPath {
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error;
    NSArray *contentArr = [fileManager contentsOfDirectoryAtPath:docPath error:&error];
    if (!contentArr.count && error) {
        NSLog(@"ContentsOfDirectory Err : %@", error.description);
    }
    return contentArr;
}

复制代码

2.2 能直接进行文件读写的数据类型

iOS中有四种简单类型能够直接进行文件读写:字符串 NSString / NSMutableString 、数组 NSArray / NSMutableArray 、字典 NSDictionary / NSMutableDictionary 、二进制数据 NSData / NSMutableData

代码示例如下:

NSString *string = @"QiShare test string ...";
[string writeToFile:path11 atomically:YES encoding:NSUTF8StringEncoding error:nil];
NSString *readStr = [NSString stringWithContentsOfFile:path11 encoding:NSUTF8StringEncoding error:nil];
NSLog(@"读取文件-字符串: %@", readStr);
    
NSArray *array = @[@"Q", @"i", @"S", @"h", @"a", @"r", @"e"];
[array writeToFile:path33 atomically:YES];
NSArray *readArr = [NSArray arrayWithContentsOfFile:path33];
NSLog(@"读取文件-数组: %@", readArr);
    
NSDictionary *dict = @{@"en":@"QiShare", @"ch":[[FileUtil alloc] init]};
[dict writeToFile:path34 atomically:YES];
NSDictionary *readDict = [NSDictionary dictionaryWithContentsOfFile:path34];
NSLog(@"读取文件-字典: %@", readDict);
    
NSData *data = [@"QiShare test data ..." dataUsingEncoding:NSUTF8StringEncoding];
[data writeToFile:path11 atomically:YES];
NSData *readData = [NSData dataWithContentsOfFile:path11];
NSLog(@"读取文件-二进制: %@", readData);
复制代码
  • 其中数组和字典中的元素对象的类型也必须是上述四种,否则不能直接写入文件;
  • 每次调用writeToFile:方法写入文件时,都会覆盖文件原有内容。

三、文件内容操作

iOS开发在涉及到文件操作的过程中,进行一些细粒度的文件内容操作时会用到NSFileHandle。一般用NSFileHandle修改文件内容有三个步骤:打开文件,获取一个NSFileHandle对象;对打开文件执行相关操作;关闭文件。NSFileHandle具体功能概括如下:

  • 打开一个文件,执行读、写或更新操作;
  • 在文件中查找指定位置;
  • 从文件中读取特定数目的字节,或将特定数目的字节写入文件中;
  • NSFileHandle类提供的方法也可以用于各种设备或套接字。

NSFileHandle 操作文件内容示例代码如下:

// NSFileHandle操作文件内容
- (void)testFileHandle {
    
    NSString *docPath = [FileUtil getDocumentsPath];
    NSString *readPath = [docPath stringByAppendingPathComponent:@"read.txt"];
    NSString *writePath = [docPath stringByAppendingPathComponent:@"write.txt"];
    NSData *data = [@"abcdefghijklmnopqrstuvwxyz" dataUsingEncoding:NSUTF8StringEncoding];
    
    NSFileManager *manager=[NSFileManager defaultManager];
    [manager createFileAtPath:readPath contents:data attributes:nil];
    [manager createFileAtPath:writePath contents:nil attributes:nil];
    [data writeToFile:readPath atomically:YES];
    
    // 打开文件 读
    NSFileHandle *readHandle = [NSFileHandle fileHandleForReadingAtPath:readPath];
    NSData *readData = [readHandle readDataToEndOfFile];
    
    // 读取文件中指定位置/指定长度的内容
    [readHandle seekToFileOffset:10];
    readData = [readHandle readDataToEndOfFile];
    NSLog(@"seekToFileOffset:10 = %@", [[NSString alloc] initWithData:readData encoding:NSUTF8StringEncoding]);
    
    [readHandle seekToFileOffset:10];
    readData = [readHandle readDataOfLength:5];
    NSLog(@"seekToFileOffset:10 = %@",[[NSString alloc]initWithData:readData encoding:NSUTF8StringEncoding]);
    [readHandle closeFile];
    
    // 打开文件 写
    NSFileHandle *writeHandle = [NSFileHandle fileHandleForWritingAtPath:writePath];
    // 注:直接覆盖文件原有内容
    [writeHandle writeData:data];
    
    // 注:覆盖了指定位置/指定长度的内容
    [writeHandle seekToFileOffset:2];
    [writeHandle writeData:[@"CDEFG" dataUsingEncoding:NSUTF8StringEncoding]];
    
    [writeHandle seekToEndOfFile];
    [writeHandle writeData:[@"一二三四五六" dataUsingEncoding:NSUTF8StringEncoding]];
    [writeHandle closeFile];
}
复制代码

工程源码地址: GitHub地址

关注我们的途径有:

QiShare(简书)

QiShare(掘金)

QiShare(知乎)

QiShare(GitHub)

QiShare(CocoaChina)

QiShare(StackOverflow)

QiShare(微信公众号)


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Ajax for Web Application Developers

Ajax for Web Application Developers

Kris Hadlock / Sams / 2006-10-30 / GBP 32.99

Book Description Reusable components and patterns for Ajax-driven applications Ajax is one of the latest and greatest ways to improve users’ online experience and create new and innovative web f......一起来看看 《Ajax for Web Application Developers》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

html转js在线工具
html转js在线工具

html转js在线工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具