通过NSString和NSData将数据写入文件

来源:互联网 发布:屏蔽一段ip的js代码 编辑:程序博客网 时间:2024/05/30 18:29

最近在学Objective-C,来做iOS开发,会陆陆续续把学习的内容补充完整。


一 将NSString对象写入文件

  在将字符串对象写入文件时,要指定字符串编码。字符串编码的作用是描述字符和代表字符的数字之间的映射关系。在ASCII码中,字符“A”对应01000001.在UTF-16编码中,字符“A”对应0000000001000001.

  Foudation框架大约支持20种不同的字符串编码,UTF编码支持几乎所有的语言。UTF分为UTF-8和UTF-16.在UTF-16中,一个字符将占用2个或者更多的字节。在UTF-8编码中,ASCII字符集中的前128个字符将占一个字节,其他的字符将在占用两个或者更多的字节。

  创建一个新的项目,类型为机遇Foundation的Command Line Tool,名称为Stingz.在main()函数中,通过NSString的类方法创建对象,然后将新创建的对象写入文件,代码如下:

#import <Foundation/Foundation.h>int main(int argc, const char * argv[]){    @autoreleasepool {                NSMutableString *str = [[NSMutableString alloc] init];        for(int i = 0; i < 10; i++){            [str appendString:@"Aaron is cool!\n"];        }        [str writeToFile:@"/tmp/cool.txt" atomically:YES encoding:NSUTF8StringEncoding error:NULL];        //创建一个文本,并将数组的中内容写入到文本中        NSLog(@"done writing /tmp/cool.txt");    }    return 0;}
  文件路径可以是绝对的或者相对的:绝对路径以/开头(/代表文件系统的根目录),而相对路径则是相对于程序当前的工作目录。相对路径不会以/开头。

二 NSError

在将字符串写入文件时可能会出现各种错误。为了让调用方有机会处理错误,苹果公司提供的很多方法都有要通过引用传入的NSError指针参数。更新上述代码,加入错误处理代码:

#import <Foundation/Foundation.h>int main(int argc, const char * argv[]){    @autoreleasepool {                NSMutableString *str = [[NSMutableString alloc] init];        for(int i = 0; i < 10; i++){            [str appendString:@"Aaron is cool!\n"];        }                NSError *error;        //声明一个指向NSError对象的指针,但是不创建相应的对象        //实际上只有当错误发生的时候,才会有writeToFile创建相应的NSError对像                BOOL success = [str writeToFile:@"/too/darned/bad.txt" atomically:YES encoding:NSUTF8StringEncoding error:&error];        //检查返回的布尔值,如果写入文件失败,就查询NSError对象并输出错误描述        if(success){            NSLog(@"done writing /tmp/cool.txt");        }else{            NSLog(@"writing /tmp/cool.txt failed:%@",[error localizedDescription]);        }    }    return 0;}
此时会报错:

2017-06-12 10:25:53.089 Stringz[596:45849] writing /tmp/cool.txt failed:The folder “bad.txt” doesn’t exist.

Program ended with exit code: 0

  下面我们看一下NSString类的writeToFile:atomically:encoding:error:方法声明如下:

- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile encoding:(NSStringEncoding)enc error:(NSError **)error;

注意方法声明中的双星号,双星号代表相应的参数是一个地址,它存放了指向NSString实例的指针。

  如果某个方法的参数包含一个要通过引用传入的NSError指针,那么这个方法的返回值应该表明(执行方法时)是否有错误发生。


三 通过NSString读取文件

  以下代码可以载入指定的文件,并将其内容存入新建的NSString对象:

 NSError *error1;        NSString *str1 = [[NSString alloc] initWithContentsOfFile:@"/etc/resolv.conf" encoding:NSASCIIStringEncoding error:&error1];                if(!str1){            NSLog(@"read failed: %@", [error1 localizedDescription]);        }else{            NSLog(@"resolv.conf looks this: %@", str1);        }
  这段代码我们以ASCII的文本载入文件的内容创建了一个新的字符串。如果失败会显示错误提示。


四 将NSData对象所保存的数据写入文件

  NSData对象“代表”内存中的某块缓冲区,可以保存相应字节数的数据。比如,可以让程序通过某个网址下载数据,并将得到的数据保存在NSData实例中。然后,要求该NSData实例将其保存的数据写入文件。

  下面创建一个新项目,名称为ImgageFetch. ImageFetch的任务是下载Google网站上的一张图片,并将下载的数据保存在一个NSData实例中,然后要求该实例将其保存的二进制数据写入文件。

#import <Foundation/Foundation.h>int main(int argc, const char * argv[]){    @autoreleasepool {        NSURL *url = [NSURL URLWithString:@"http://www.google.com/images/logos/ps_logo2.png"];        NSURLRequest *request = [NSURLRequest requestWithURL:url];        NSError *error = nil;        NSData *data= [NSURLConnection sendSynchronousRequest:request returningResponse:NULL error:&error];                if(!data){            NSLog(@"fetch failed: %@", [error localizedDescription]);            return 1;        }                NSLog(@"The file is %lu bytes", (unsigned long)[data length]);        BOOL written = [data writeToFile:@"/tmp/baidu.png" options:0 error:&error];                if(!written){            NSLog(@"write failed: %@", [error localizedDescription]);        }        NSLog(@"Success!");            }    return 0;}

- (BOOL)writeToFile:(NSString *)path options:(NSDataWritingOptions)writeOptionsMask error:(NSError **)errorPtr;
  这个方法在保存数据时所使用的设置要通过options参数传入。最常见的设置是NSDataWritingAtomic.假设程序之前已经下载了一张图片,现在正在重新下载,则要用新的文件替换旧的。如果在覆盖文件的时候计算机断电了,那么写到一半的文件将无法使用。如果要保证文件的完整性就应该使用具备原子性的写操作。
 BOOL written = [data writeToFile:@"/tmp/baidu.png" options:NSDataWritingAtomic error:&error];                if(!written){            NSLog(@"write failed: %@", [error localizedDescription]);        }        NSLog(@"Success!");
  现在。NSData对象会先将数据写入临时文件,成功后再移动至指定的路径。这样,要么生成一个完整的文件,要么什么都没有。


五 从文件读取数据并存入NSData对象

  再末尾加入两段代码就可以了。

             NSData *readData = [NSData dataWithContentsOfFile:@"/tmp/google.png"];        NSLog(@"The file read from the disk has %lu bytes", (unsigned long)[readData length]);