Level: ★★☆☆ Tag: iOS file manipulation SandBox QiFileManager author: Dac_1033 Review: QiShare team

In the process of iOS development, network error does not return the correct data, then can read local data display to the user to optimize the user experience, and at the time of normal network request to update the local data, the local data are usually exist sandbox directories in the file, here we make a brief introduction of iOS development of file operations. Attached: Apple’s official file system programming guide.

About the iOS file system

1.1 SandBox

Each app in iOS has a separate, closed, secure directory called a sandbox, which typically houses package files (executables), images, audio, videos, PList files, SQLite databases, and other files. Each app’s sandbox is independent, and applications cannot directly access each other. Apple’s official website divides sandboxes into three categories (Bundle Container, Data Container, and iClound Container), as shown below:

The sandbox structure in the figure above is actually different from xiaobian’s understanding. We will not study the specific sandbox structure for the moment. When developing an iOS application, we can only see the root directory in the sandbox and the three default generated folders Documents, Library and Tmp. These are the most important ones.

directory describe
AppName.app The package directory for the application, which contains the application itself. Because the application must be signed, the contents of this directory cannot be modified at run time, otherwise the application will not start.
Documents/ Save application important data files and user data files, etc. This is where most of the user’s data is stored (for example, photos or music files downloaded from the Web). This folder is automatically backed up when the application is updated, and the data in it is automatically synchronized when you connect to iTunes.

The contents of this directory are backed up by iTunes and iCloud.
Library/ This directory has two subdirectories for creating subfolders. Can be used to place data that you want to back up but don’t want users to see. Folders in this path, except for Caches, are backed up by iTunes;

The contents of this directory are backed up by iTunes and iCloud
Library/Caches Save support files and cache files generated while the application is in use (saving information needed for the application to start up again), and log files preferably in this directory as well;

ITunes does not back up this directory, and data in this directory may be wiped by other tools.
Library/Preferences Save the application’s preferences file. This is where the data and plist files created by the NSUserDefaults class go;

The contents of this directory are backed up by iTunes and iCloud.
Tmp/ Use this directory to write temporary files that do not need to be kept between application startup. Your application should delete files in this directory when it is no longer needed. However, when your application is not running, the system may clear this directory.

ITunes or iCloud will not back up the contents of this directory.
1.2 Obtaining the Sandbox Directory
- (void)testNSString *homePath = NSHomeDirectory(); NSLog(@"NSHomeDirectory: %@", homePath); NSString * TMP = NSTemporaryDirectory(); NSLog(@"NSTemporaryDirectory: %@", tmp); / / get the Document directory paths NSArray * = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory NSUserDomainMask, YES); NSString *docPath = [paths lastObject]; NSLog(@"NSDocumentDirectory: %@", docPath); / / get the Library directory paths = NSSearchPathForDirectoriesInDomains (NSLibraryDirectory NSUserDomainMask, YES). NSString *libPath = [paths lastObject]; NSLog(@"NSLibraryDirectory: %@", libPath); / / get the Library Cache paths = NSSearchPathForDirectoriesInDomains (NSCachesDirectory NSUserDomainMask, YES). NSString *cachesPath = [paths lastObject]; NSLog(@"NSCachesDirectory: %@", cachesPath);
}
Copy the code
1.3 Common path processing methods

The system implements an extension to NSString tensions in the NSPathUtilities class, NSStringPathExtensions, which defines a number of methods specifically to deal with paths:

- (NSArray *)pathComponents;
- (NSString *)lastPathComponent;
- (NSString *)stringByDeletingLastPathCpmponent;
- (NSString *)stringByAppendingPathConmponent:(NSString *)str;
- (NSString *)pathExtension;
- (NSString *)stringByDeletingPathExtension;
- (NSString *)stringByAppendingPathExtension:(NSString *)str;
Copy the code
1.4 NSBundle in iOS Engineering

The bundle is a directory that contains resources (such as images, sounds, code files, NIB files, etc.) that the application will use. App itself is no different from other files in the system. In fact, app package contains niB files, compiled and connected codes and directories of other resources. We call app package directory the main bundle of the app. In iOS development, you can use the NSBundle class to manipulate bundles and the resources in them. Example code for using NSBundle is described in the official NSBundle documentation as follows:

NSBundle *mainBundle = [NSBundle mainBundle]; // Add a custom Test. Bundle NSString * to app mainBundletestBundlePath = [mainBundle pathForResource:@"Test" ofType:@"bundle"];
NSBundle *testBundle = [NSBundle bundleWithPath:testBundlePath]; NSString *resPath = [testBundle pathForResource:@"sound02" ofType:@"wav"];
NSLog(@"Custom path to resources in bundle: %@", resPath); UIImage *img = [UIImage imageNamed:[NSString stringWithFormat:@"Test.bundle/%@"The @"logo_img_02"]];
NSLog(@"Custom bundle image: %@", img);
Copy the code

2. File operation

2.1 File Paths and files
// get the sandbox root path + (NSString *)getHomePath {returnNSHomeDirectory(); } // getTmpPath + (NSString *)getTmpPath {returnNSTemporaryDirectory(); } // getDocumentsPath + (NSString *)getDocumentsPath {NSArray *pathArr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *path = [pathArr firstObject];returnpath; } // getLibraryPath + (NSString *)getLibraryPath {NSArray *pathArr = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); NSString *path = [pathArr firstObject];returnpath; } // getLibraryCachePath + (NSString *)getLibraryCachePath {NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); NSString *path = [paths firstObject];returnpath; } // check whether files and folders exist. + (BOOL)fileExistsAtPath:(NSString *)path isDirectory:(BOOL *)isDir {NSFileManager *fileManager = [NSFileManager defaultManager]; BOOL exist = [fileManager fileExistsAtPath:path isDirectory:isDir];returnexist; } // create path + (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(! {// note: Directly create does not overwrite the original folder [fileManager createDirectoryAtPath: path withIntermediateDirectories: YES attributes: nil error: nil]; }} // createFile + (NSString *)createFile:(NSString *)filePath fileName:(NSString *)fileName {// create path [self createDirectory:filePath]; // create file NSFileManager *fileManager = [NSFileManager defaultManager]; // Create file 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(! [fileManager createFileAtPath:path contents:nil attributes:nil]; }returnpath; } // copy files or folders + (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); }} // move file or folder + (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); }} // delete files or folders + (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); }} / / to get all the content directory + (NSArray *) getContentsOfDirectoryAtPath: (nsstrings *) 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;
}

Copy the code
2.2 Data types that can directly read and write files

There are four simple types in iOS that can directly read and write files: String nsstrings/NSMutableString NSDictionary, NSArray array/NSMutableArray, dictionary/NSMutableDictionary NSData/NSMutableData, binary data. A code example is as follows:

NSString *string = @"QiShare test string ...";
[string writeToFile:path11 atomically:YES encoding:NSUTF8StringEncoding error:nil];
NSString *readStr = [NSString stringWithContentsOfFile:path11 encoding:NSUTF8StringEncoding error:nil];
NSLog(@"Read file - string: %@".readStr);
    
NSArray *array = @[@"Q"The @"i"The @"S"The @"h"The @"a"The @"r"The @"e"];
[array writeToFile:path33 atomically:YES];
NSArray *readArr = [NSArray arrayWithContentsOfFile:path33];
NSLog(@"Read file - Array: %@".readArr);
    
NSDictionary *dict = @{@"en": @"QiShare"The @"ch":[[FileUtil alloc] init]};
[dict writeToFile:path34 atomically:YES];
NSDictionary *readDict = [NSDictionary dictionaryWithContentsOfFile:path34];
NSLog(@"Read file - dictionary: %@".readDict);
    
NSData *data = [@"QiShare test data ..." dataUsingEncoding:NSUTF8StringEncoding];
[data writeToFile:path11 atomically:YES];
NSData *readData = [NSData dataWithContentsOfFile:path11];
NSLog(@"Read file - binary: %@".readData);
Copy the code
  • The type of the element object in the array and dictionary must also be the above four types, otherwise it cannot be directly written to the file;
  • Each time the writeToFile: method is called to write to a file, the original contents of the file are overwritten.

3. Operation of file contents

When iOS development involves file operations, NSFileHandle is used for some fine-grained file content operations. Generally, there are three steps to modify the file content with NSFileHandle: Open the file and obtain an NSFileHandle object; Perform operations on open files; Close the file. The specific functions of NSFileHandle are summarized as follows:

  • Open a file to read, write, or update;
  • Finds the specified location in a file.
  • Read a specified number of bytes from or write a specified number of bytes to a file;
  • The NSFileHandle class provides methods that can also be used on a variety of devices or sockets.

Example code for manipulating file contents with NSFileHandle is as follows:

// NSFileHandle handles file contents - (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]; // Open the file to read NSFileHandle *readHandle = [NSFileHandle fileHandleForReadingAtPath:readPath];
    NSData *readData = [readHandle readDataToEndOfFile]; // Read the contents of the specified position/specified length in the file [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]; / / open the file write NSFileHandle * writeHandle = [NSFileHandle fileHandleForWritingAtPath: writePath]; [writeHandle writeData:data]; WriteHandle seekToFileOffset:2; writeHandle seekToFileOffset:2; [writeHandle writeData:[@"CDEFG" dataUsingEncoding:NSUTF8StringEncoding]];
    
    [writeHandle seekToEndOfFile];
    [writeHandle writeData:[@"One, two, three, four, six." dataUsingEncoding:NSUTF8StringEncoding]];
    [writeHandle closeFile];
}
Copy the code

Project source address: GitHub address


QiShare(Simple book) QiShare(digging gold) QiShare(Zhihu) QiShare(GitHub) QiShare(CocoaChina) QiShare(StackOverflow) QiShare(wechat public account)

IOS Keyframe animation iOS get device current language and region iOS write high quality Objective-C code (seven)