iphone 輸入/輸出流非同步讀寫資料
阿新 • • 發佈:2019-02-18
1、首先是往檔案裡寫入資料
WriteFile.h
#import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @class NoteDb; @interface WriteFile : NSObject<NSStreamDelegate>{ //檔案地址 NSString *parentDirectoryPath; //輸出流,寫資料 NSOutputStream *asyncOutputStream; //寫資料的內容 NSData *outputData; //位置及長度 NSRange outputRange; //資料的來源 NoteDb *aNoteDb; } @property (nonatomic,retain) NSData *outputData; @property (nonatomic,retain) NoteDb *aNoteDb; //寫資料 -(void)write; @end
實現檔案WriteFile.m
#import "WriteFile.h" #import "NoteDb.h" @implementation WriteFile @synthesize outputData,aNoteDb; -(id)init{ self=[super init]; if (!self) { [self release]; return nil; } outputData=[[NSData alloc]init]; aNoteDb=[[NoteDb alloc]init]; return self; } -(void)write{ //NSLog(@"%@",self.aNoteDb); //沙盒路徑 NSArray *paths= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; //檔名字是note.txt NSString *path = [documentsDirectory stringByAppendingPathComponent:@"note.txt"]; [asyncOutputStream release]; parentDirectoryPath = path; //資料來源 NSData *tmpdata = [NSKeyedArchiver archivedDataWithRootObject:self.aNoteDb.noteList]; //self.outputData=[[NSData alloc]initWithData:tmpdata]; self.outputData=tmpdata; //位置從哪開始 outputRange.location=0; //建立檔案 [[NSFileManager defaultManager] createFileAtPath:parentDirectoryPath contents:nil attributes:nil]; //初始化輸出流 asyncOutputStream = [[NSOutputStream alloc] initToFileAtPath: parentDirectoryPath append: NO]; //回撥方法, [asyncOutputStream setDelegate: self]; //非同步處理, [asyncOutputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; //開啟非同步輸出流 [asyncOutputStream open]; } -(void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent{ // NSLog(@"as"); NSOutputStream *outputStream = (NSOutputStream*) theStream; BOOL shouldClose = NO; switch (streamEvent) { case NSStreamEventHasSpaceAvailable://讀事件 { //緩衝區 uint8_t outputBuf [1]; //長度 outputRange.length = 1; //把資料放到緩衝區中 [outputData getBytes:&outputBuf range:outputRange]; //把緩衝區中的東西放到輸出流 [outputStream write: outputBuf maxLength: 1]; //判斷data資料是否讀完 if (++outputRange.location == [outputData length]) { shouldClose = YES; } break; } case NSStreamEventErrorOccurred: { //出錯的時候 NSError *error = [theStream streamError]; if (error != NULL) { UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle: [error localizedDescription] message: [error localizedFailureReason] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [errorAlert show]; [errorAlert release]; } shouldClose = YES; break; } case NSStreamEventEndEncountered: shouldClose = YES; } if (shouldClose) { //當出錯或者寫完資料,把執行緒移除 [outputStream removeFromRunLoop: [NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; //最後關掉輸出流 [theStream close]; } } -(void)dealloc{ [outputData release]; [aNoteDb release]; [super dealloc]; } @end
2、其次是從檔案裡讀出資料
ReadFile.h
#import <Foundation/Foundation.h> @class NoteDb; @interface ReadFile : NSObject<NSStreamDelegate>{ //路徑 NSString *parentDirectoryPath; //非同步輸出流 NSInputStream *asyncInputStream; //讀出來的資料 NSMutableData *resultData; //返回去的資料 NoteDb *aNoteDb; } @property(nonatomic,retain)NoteDb *aNoteDb; @property (nonatomic, retain) NSMutableData *resultData; //開始讀資料 -(void)read; //讀出來的資料追加到resultData上 - (void)appendData:(NSData*)_data; // - (void)dataAtNoteDB; //返回去的資料 - (NoteDb*)getNoteDb; @end
實現檔案ReadFile.m
#import "ReadFile.h"
#import "NoteDb.h"
#import "NoteList.h"
#import "WriteFile.h"
@implementation ReadFile
@synthesize aNoteDb,resultData;
-(id)init{
self=[super init];
//aNoteDb=[[NoteDb alloc]init];
resultData=[[NSMutableData alloc]init];
return self;
}
-(void)read{
//沙盒路徑
NSArray *paths= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//檔名
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"note.txt"];
/*
if(![[NSFileManager defaultManager]fileExistsAtPath:path]){
//如果不存在,就新建
WriteFile *file=[[WriteFile alloc]init];
[file write];
[file release];
}else{
NSLog(@"有note.txt檔案");
}
*/
[asyncInputStream release];
parentDirectoryPath = path;
//非同步輸入流初始化,並把賦於地址
asyncInputStream =
[[NSInputStream alloc] initWithFileAtPath: parentDirectoryPath];
//設定代理(回撥方法、委託)
[asyncInputStream setDelegate: self];
//設定執行緒,新增執行緒,建立執行緒:Runloop顧名思義就是一個不停的迴圈,不斷的去check輸入
[asyncInputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
//開啟執行緒
[asyncInputStream open];
}
//追加資料
- (void)appendData:(NSData*)_data{
[resultData appendData:_data];
}
//回撥方法,不停的執行
-(void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent{
BOOL shouldClose = NO;
NSInputStream *inputStream = (NSInputStream*) theStream;
//NSLog(@"as");
switch (streamEvent)
{
case NSStreamEventHasBytesAvailable:
{
//讀資料
//讀取的位元組長度
NSInteger maxLength = 128;
//緩衝區
uint8_t readBuffer [maxLength];
//從輸出流中讀取資料,讀到緩衝區中
NSInteger bytesRead = [inputStream read: readBuffer
maxLength:maxLength];
//如果長度大於0就追加資料
if (bytesRead > 0)
{
//把緩衝區中的資料讀成data資料
NSData *bufferData = [[NSData alloc]
initWithBytesNoCopy:readBuffer
length:bytesRead
freeWhenDone:NO];
//追加資料
[self appendData:bufferData];
//release掉data
[bufferData release];
}
break;
}
case NSStreamEventErrorOccurred:
{
//讀的時候出錯了
NSError *error = [theStream streamError];
if (error != NULL)
{
UIAlertView *errorAlert = [[UIAlertView alloc]
initWithTitle: [error localizedDescription]
message: [error localizedFailureReason]
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[errorAlert show];
[errorAlert release];
}
shouldClose = YES;
break;
}
case NSStreamEventEndEncountered:
{
shouldClose = YES;
//資料讀完就返回資料
[self dataAtNoteDB];
[theStream close];
}break;
}
if (shouldClose)
{
//當檔案讀完或者是讀到出錯時,把執行緒移除
[inputStream removeFromRunLoop: [NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
//並關閉流
[theStream close];
}
}
-(void) dataAtNoteDB{
aNoteDb=nil;
aNoteDb=[[NoteDb alloc]init];
aNoteDb.noteList = [NSKeyedUnarchiver unarchiveObjectWithData:resultData];
//NSLog(@"%@",aNoteDb);
/*
for (id tmp in aNoteDb.noteList.noteArray)
{
NSLog(@"tmp = %@",tmp);
}
*/
}
- (NoteDb*)getNoteDb{
return self.aNoteDb;
}
-(void)dealloc{
[aNoteDb release];
[resultData release];
[super dealloc];
}
@end
ok!本部落格是我自己的練習,有好多地方沒有講太清楚,還請諒解!