Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c NSFileHandle fileHandleForReadingFromURL有人能给我解释一下吗?_Objective C_Nsurl_Nsfilehandle - Fatal编程技术网

Objective c NSFileHandle fileHandleForReadingFromURL有人能给我解释一下吗?

Objective c NSFileHandle fileHandleForReadingFromURL有人能给我解释一下吗?,objective-c,nsurl,nsfilehandle,Objective C,Nsurl,Nsfilehandle,我正在尝试根据Dave DeLong的输入流创建一个定制的输入流,该输入流还允许通过NSURL从服务器读取数据。到目前为止,我有这样一种方法,适用于本地文件: @interface RJRStreamReader : NSObject { @private NSFileHandle *fileHandle; NSStringEncoding encoding; NSString *lineDelimiter; unsigned long long curr

我正在尝试根据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
将始终为空,因为
[nsfilehandlefilehandleforreadingfromURL:remoteURL]
返回的
NSFileHandle
似乎总是返回nil,没有任何错误

这是我的代码中的一个bug还是他们的一个未记录的特性


谢谢

好的,这是我的问题:

根据

fileHandleForReadingFromURL:错误: 返回初始化的文件句柄,用于读取指定URL处的文件、设备或命名套接字

它不读取服务器URL,这导致我采用这种方法(我希望人们能为我编辑它,因为它需要延迟加载、优化等)

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

好的,这是我的问题:

根据

fileHandleForReadingFromURL:错误: 返回初始化的文件句柄,用于读取指定URL处的文件、设备或命名套接字

它不读取服务器URL,这导致我采用这种方法(我希望人们能为我编辑它,因为它需要延迟加载、优化等)

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