이것은 나를 혼란스럽게합니다. iOS에서 6MB CSV 파일을 한 줄씩 읽으려고합니다. 나는 일반 C 파일 포인터와 NSInputStream 폴링을 사용해 보았지만 가장 깨끗한 느낌의 다음에 정착했다. 세 가지 방법 모두 성공한 결과를 반환하는 무작위 블록처럼 보이지만 모든 null 바이트로 버퍼를 채 웁니다. 나는 "무작위"라고 말하지만 일관성이있다. 프로그램이 다시 실행될 때 읽기가 정확히 동일한 시점에서 작동하지 않으며 읽기 횟수가 의심 스럽습니다 (아래에서 더 자세히 설명합니다).비동기 큰 파일을 읽으면 iOS에서 null 읽기 블록이 발생합니다.
- (id)initWithFileAtPath:(NSString *)path {
if ((self = [super init])) {
filePath = [path copy];
queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 1;
buffer = [[NSMutableString alloc] init];
bytes = malloc(CHUNK_SIZE * sizeof(UTF8Char));
}
return self;
}
- (void)dealloc {
[filePath release];
[queue release];
[buffer release];
free(bytes);
[super dealloc];
}
- (void)stream:(NSInputStream *)stream handleEvent:(NSStreamEvent)eventCode {
switch (eventCode) {
case NSStreamEventOpenCompleted:
break;
case NSStreamEventHasBytesAvailable:
[queue addOperationWithBlock:^{
[self readChunk: stream];
[self drainBuffer];
}];
break;
case NSStreamEventEndEncountered:
if ([buffer length] > 0) {
[delegate reader:self didReadLine:[NSString stringWithString:buffer]];
[buffer setString:@""];
}
[stream close];
[stream removeFromRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[stream release];
[delegate readerDidFinishReading:self];
break;
default:
NSLog(@"StreamReader: event %d", eventCode);
break;
}
}
- (void)enumerateLines {
NSInputStream *stream = [[NSInputStream alloc] initWithFileAtPath:filePath];
stream.delegate = self;
[stream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[stream open];
}
- (void)readChunk: (NSInputStream*)stream {
NSInteger readSize = [stream read:bytes maxLength:CHUNK_SIZE];
if (readSize) {
if (bytes[0] == '\0') {
NSLog(@"null buffer %d", readSize);
}
NSString *string = [[NSString alloc] initWithBytes:bytes
length:readSize
encoding:NSUTF8StringEncoding];
[buffer appendString:string];
[string release];
} else {
NSLog(@"StreamReader: read zero bytes");
}
}
- (void)drainBuffer {
static NSCharacterSet *newlines = nil;
if (newlines == nil) {
newlines = [NSCharacterSet newlineCharacterSet];
}
NSRange newlinePos;
while ((newlinePos = [buffer rangeOfCharacterFromSet:newlines]).location != NSNotFound) {
NSString *line = [buffer substringToIndex:newlinePos.location];
// remove the line from the buffer along with line separator
[buffer deleteCharactersInRange: (NSRange){0, [line length]}];
while ([buffer length] > 0 && [newlines characterIsMember:[buffer characterAtIndex:0]]) {
[buffer deleteCharactersInRange:(NSRange){0, 1}];
}
[delegate reader:self didReadLine: line];
}
}
는 6 메가 바이트 파일을 읽는 동안, 두 번 나는 96의 시리즈를 얻을 수 chunk_size 인 경우 수 chunk_size가 1024 일 때 512 (192)의 일련있을 것 "나쁜 읽기" "나쁜 읽기". "나쁜 독서"란 무엇을 의미합니까? NSInputStream 읽기 메시지는 성공을 반환하며 대리자 콜백에서 오류 이벤트가 발생하지 않습니다. 그러나 bytes
버퍼는 모든 null 값을가집니다.
- 아이폰 OS 7.0.4, 아이 패드 2
- 함께 aprox에 파일 크기를 감소 시뮬레이터
- 에서 발생하지 않습니다 바탕 화면
- 에 발생하지 않습니다. 1MB는 iPad에서 문제를 "고칩니다."
메인 UI 스레드에서 리더 클래스를 인스턴스화하는 것이 가장 가치가 있습니다.
그래서 ... 나는 여기서 뭔가 미묘하게 (또는 미묘하게) 잘못하고있는 것입니까? 아니면 어떤 종류의 모호한 iOS 버그를 발견 했습니까?
나는 NSLog 명령문을 추가하고, 내 버그를 찾으려고 노력하고 있습니다. 이 시점에서 심각한 문제가있는 파일 시스템의 확률은 매우 떨어진다. –