1. 程式人生 > >iphone 輸入/輸出流非同步讀寫資料

iphone 輸入/輸出流非同步讀寫資料

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!本部落格是我自己的練習,有好多地方沒有講太清楚,還請諒解!