nsfilehandle filehandleforreadingfromurl誰かが私にこれを説明してくれませんか?
-
29-09-2019 - |
質問
Dave Delongに基づいたカスタマイズされた入力ストリームを作成しようとしています ここ また、NSURLを介してサーバーからデータを読み取ることもできます。これまでのところ、私はこのアプローチを持っています。これはローカルファイルに正常に機能します。
@interface RJRStreamReader : NSObject {
@private
NSFileHandle *fileHandle;
NSStringEncoding encoding;
NSString *lineDelimiter;
unsigned long long currentOffset;
unsigned long long totalFileLength;
int chunkSize;
}
@property(readwrite, assign) NSStringEncoding encoding;
@property(readwrite, assign) unsigned long long currentOffset;
@property(readwrite, copy) NSString *lineDelimiter;
@property(readwrite, assign) int chunkSize;
@property(readonly) unsigned long long totalFileLength;
-(id) initWithLocalFile:(NSString *) fileName;
-(id) initWithURL:(NSURL *) remoteURL;
-(id) initWithFileHandle:(NSFileHandle *) fh;
-(NSString *) readToEnd;
-(NSString *) readLine;
/**
@summary Reads a block of bytes from a stream
@param blockLen the number of bytes to read
@returns a string containing the data from the bytes read
*/
-(NSString *) readBlock:(int) blockLen;
@end
そして私の実装:
@implementation RJRStreamReader
@synthesize currentOffset, lineDelimiter, encoding, chunkSize, totalFileLength;
-(id) initWithLocalFile:(NSString *)fileName
{
if (self = [super init])
{
fileHandle = [NSFileHandle fileHandleForReadingAtPath:fileName];
if (fileHandle == nil)
{
[self release];
return nil;
}
chunkSize = 10;
encoding = NSUTF8StringEncoding;
lineDelimiter = [[NSString alloc] initWithString:@"\n"];
[fileHandle retain];
currentOffset = 0ULL;
[fileHandle seekToEndOfFile];
totalFileLength = [fileHandle offsetInFile];
}
return self;
}
-(id) initWithURL:(NSURL *)remoteURL
{
if (self = [super init])
{
NSError *err = nil;
fileHandle = [NSFileHandle fileHandleForReadingFromURL:remoteURL error:&err];
if (err)
{
NSLog(@"Error occurred, aborting. Details: %@", err);
[self release];
return nil;
}
chunkSize = 10;
encoding = NSUTF8StringEncoding;
lineDelimiter = [[NSString alloc] initWithString:@"\n"];
[fileHandle retain];
currentOffset = 0ULL;
[fileHandle seekToEndOfFile];
totalFileLength = [fileHandle offsetInFile];
}
return self;
}
-(id) initWithFileHandle:(NSFileHandle *) fh
{
if (self = [super init])
{
fileHandle = fh;
if (!fh)
{
[self release];
[NSException raise:@"FH cannot be nil!" format:@"FH cannot be nil!"];
return nil;
}
chunkSize = 10;
encoding = NSUTF8StringEncoding;
lineDelimiter = [[NSString alloc] initWithString:@"\n"];
[fileHandle retain];
currentOffset = 0ULL;
[fileHandle seekToEndOfFile];
totalFileLength = [fileHandle offsetInFile];
}
return self;
}
-(NSString *) readBlock:(int)blockLen
{
if (currentOffset >= totalFileLength) { return nil; }
[fileHandle seekToFileOffset:currentOffset];
NSData *data = [fileHandle readDataOfLength:blockLen];
currentOffset += blockLen;
[fileHandle seekToFileOffset:currentOffset];
return [[[NSString alloc] initWithData:data encoding:encoding] autorelease];
}
-(NSString *) readLine
{
/*
if you want to see the code for this method, visit this link:
https://stackoverflow.com/questions/3707427/how-to-read-data-from-nsfilehandle-line-by-line
it is exactly the same
*/
}
-(NSString *) readToEnd
{
if (currentOffset >= totalFileLength) { return nil; }
[fileHandle seekToFileOffset:currentOffset];
NSData *data = [fileHandle readDataToEndOfFile];
currentOffset = totalFileLength;
[fileHandle seekToEndOfFile];
return [[[NSString alloc] initWithData:data encoding:encoding] autorelease];
}
-(void) dealloc
{
[fileHandle closeFile];
[fileHandle release];
[lineDelimiter release];
[super dealloc];
}
@end
問題は、私がこのようにそれを使用しようとするときです:
RJRStreamReader *stream = [[RJRStreamReader alloc] initWithURL:[NSURL URLWithString:@"http://www.stackoverflow.com/robots.txt"];
NSString *s = [stream readToEnd];
s
なぜなら、常に空になります NSFileHandle
によって返されます [NSFileHandle fileHandleForReadingFromURL:remoteURL]
エラーなしで常にnilを返しているようです。
これは私のコードのバグですか、それとも彼らの文書化されていない機能ですか?
ありがとう
解決
わかりました、これは私の問題です:
による ドキュメンテーション
filehandleforreadingfromurl:エラー:指定されたURLでファイル、デバイス、または名前付きソケットを読み取るために初期化されたファイルハンドルを返します。
サーバーのURLからは読みません。これにより、このアプローチに導かれました(怠zyなロード、最適化などが必要なので、人々がこれを編集してほしいです。)
rjrstreamreader.h:
@interface RJRStreamReader : NSObject {
@private
NSData *data;
NSStringEncoding encoding;
NSString *lineDelimiter;
unsigned long long currentOffset;
unsigned long long totalFileLength;
int chunkSize;
}
@property(readwrite, assign) NSStringEncoding encoding;
@property(readwrite, assign) unsigned long long currentOffset;
@property(readwrite, copy) NSString *lineDelimiter;
@property(readwrite, assign) int chunkSize;
@property(readonly) unsigned long long totalFileLength;
-(id) initWithLocalFile:(NSString *) fileName;
-(id) initWithURL:(NSURL *) remoteURL;
-(id) initWithFileHandle:(NSFileHandle *) fh;
-(id) initWithData:(NSData *) theData;
-(NSString *) readToEnd;
-(NSString *) readLine;
/**
@summary Reads a block of bytes from a stream
@param blockLen the number of bytes to read
@returns a string containing the data from the bytes read
*/
-(NSString *) readBlock:(int) blockLen;
@end
rjrstreamreader.m:
@implementation RJRStreamReader
@synthesize currentOffset, lineDelimiter, encoding, chunkSize, totalFileLength;
-(id) initWithLocalFile:(NSString *)fileName
{
if (self = [super init])
{
NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:fileName];
if (fileHandle == nil)
{
[self release];
return nil;
}
data = [[fileHandle readDataToEndOfFile] retain];
chunkSize = 10;
encoding = NSUTF8StringEncoding;
lineDelimiter = [[NSString alloc] initWithString:@"\n"];
currentOffset = 0ULL;
[fileHandle seekToEndOfFile];
totalFileLength = [fileHandle offsetInFile];
[fileHandle closeFile];
}
return self;
}
-(id) initWithURL:(NSURL *)remoteURL
{
if (self = [super init])
{
NSError *err = nil;
NSURLResponse *resp = nil;
data = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:remoteURL] returningResponse:&resp error:&err];
if (err)
{
NSLog(@"Error occurred, aborting. Details: %@", err);
[self release];
return nil;
}
chunkSize = 10;
encoding = NSUTF8StringEncoding;
lineDelimiter = [[NSString alloc] initWithString:@"\n"];
[data retain];
currentOffset = 0ULL;
totalFileLength = [data length];
}
return self;
}
-(id) initWithFileHandle:(NSFileHandle *) fh
{
if (self = [super init])
{
if (!fh)
{
[self release];
[NSException raise:@"FH cannot be nil!" format:@"FH cannot be nil!"];
return nil;
}
unsigned long long pos = [fh offsetInFile];
data = [[fh readDataToEndOfFile] retain];
chunkSize = 10;
encoding = NSUTF8StringEncoding;
lineDelimiter = [[NSString alloc] initWithString:@"\n"];
currentOffset = 0ULL;
[fh seekToEndOfFile];
totalFileLength = [fh offsetInFile];
[fh seekToFileOffset:pos];
}
return self;
}
-(id) initWithData:(NSData *)theData
{
if (self = [super init])
{
data = [theData retain];
chunkSize = 10;
encoding = NSUTF8StringEncoding;
lineDelimiter = [[NSString alloc] initWithString:@"\n"];
currentOffset = 0ULL;
totalFileLength = [data length];
}
return self;
}
-(NSString *) readBlock:(int)blockLen
{
if (currentOffset >= totalFileLength) { return nil; }
NSData *tmpdata = [data subdataWithRange:NSMakeRange(currentOffset, blockLen)];
currentOffset += blockLen;
return [[[NSString alloc] initWithData:tmpdata encoding:encoding] autorelease];
}
-(NSString *) readLine
{
if (currentOffset >= totalFileLength) { return nil; }
NSData * newLineData = [lineDelimiter dataUsingEncoding:NSUTF8StringEncoding];
//[fileHandle seekToFileOffset:currentOffset];
NSMutableData * currentData = [[NSMutableData alloc] init];
BOOL shouldReadMore = YES;
NSAutoreleasePool * readPool = [[NSAutoreleasePool alloc] init];
while (shouldReadMore) {
if (currentOffset >= totalFileLength) { break; }
NSData *chunk = [data subdataWithRange:NSMakeRange(currentOffset, chunkSize)];
NSRange newLineRange = [chunk rangeOfData_dd:newLineData];
if (newLineRange.location != NSNotFound) {
//include the length so we can include the delimiter in the string
chunk = [chunk subdataWithRange:NSMakeRange(0, newLineRange.location)];
shouldReadMore = NO;
}
[currentData appendData:chunk];
currentOffset += [chunk length];
}
[readPool release];
NSString * line = [[NSString alloc] initWithData:currentData encoding:NSUTF8StringEncoding];
[currentData release];
return [line autorelease];
}
-(NSString *) readToEnd
{
if (currentOffset >= totalFileLength) { return nil; }
NSData *tmpdata = [data subdataWithRange:NSMakeRange(currentOffset, totalFileLength - currentOffset)];
currentOffset = totalFileLength;
return [[[NSString alloc] initWithData:tmpdata encoding:encoding] autorelease];
}
-(void) dealloc
{
[data release];
[lineDelimiter release];
[super dealloc];
}
@end
所属していません StackOverflow