frs*_*rsh 8 iphone base64 objective-c nsdata nsfilehandle
更新4
Per Greg的建议我创建了一对图像/文本,使用100k块显示从37k图像到base64编码的输出.由于文件只有37k,所以可以说循环只迭代一次,因此没有附加任何内容.另一对使用10k块显示从相同的37k图像到base64编码的输出.由于文件是37k,循环迭代四次,并且数据被明确附加.
对这两个文件进行差异显示,在10kb块文件上有一个很大的区别,它从第214行开始,到第640行结束.
更新3
这是我的代码现在的位置.清理了一下但仍产生相同的效果:
// Read data in chunks from the original file
[originalFile seekToEndOfFile];
NSUInteger fileLength = [originalFile offsetInFile];
[originalFile seekToFileOffset:0];
NSUInteger chunkSize = 100 * 1024;
NSUInteger offset = 0;
while(offset < fileLength) {
NSData *chunk = [originalFile readDataOfLength:chunkSize];
offset += chunkSize;
// Convert the chunk to a base64 encoded string and back into NSData
NSString *base64EncodedChunkString = [chunk base64EncodedString];
NSData *base64EncodedChunk = [base64EncodedChunkString dataUsingEncoding:NSASCIIStringEncoding];
// Write the encoded chunk to our output file
[encodedFile writeData:base64EncodedChunk];
// Cleanup
base64EncodedChunkString = nil;
base64EncodedChunk = nil;
// Update progress bar
[self updateProgress:[NSNumber numberWithInt:offset] total:[NSNumber numberWithInt:fileLength]];
}
更新2
所以看起来大于100 KB的文件被加扰,但100 KB以下的文件很好.显而易见,我的缓冲区/数学/等等有些东西已经关闭,但我在这个问题上迷失了.可能是时候称它为一天,但我很想睡觉,这个解决了.
这是一个例子:
更新1
经过一些测试后,我发现相同的代码可以很好地处理小图像,但不适用于任何大小的大图像或视频.绝对看起来像一个缓冲问题,对吧?
嘿那里,尝试通过循环遍历并对一个小块进行一次编码来对base64进行编码.一切似乎都有效,但文件总是被破坏了.我很好奇是否有人能指出我在哪里可能会出错:
NSFileHandle *originalFile, *encodedFile;
self.localEncodedURL = [NSString stringWithFormat:@"%@-base64.xml", self.localURL];
// Open the original file for reading
originalFile = [NSFileHandle fileHandleForReadingAtPath:self.localURL];
if (originalFile == nil) {
[self performSelectorOnMainThread:@selector(updateStatus:) withObject:@"Encoding failed." waitUntilDone:NO];
return;
}
encodedFile = [NSFileHandle fileHandleForWritingAtPath:self.localEncodedURL];
if (encodedFile == nil) {
[self performSelectorOnMainThread:@selector(updateStatus:) withObject:@"Encoding failed." waitUntilDone:NO];
return;
}
// Read data in chunks from the original file
[originalFile seekToEndOfFile];
NSUInteger length = [originalFile offsetInFile];
[originalFile seekToFileOffset:0];
NSUInteger chunkSize = 100 * 1024;
NSUInteger offset = 0;
do {
NSUInteger thisChunkSize = length - offset > chunkSize ? chunkSize : length - offset;
NSData *chunk = [originalFile readDataOfLength:thisChunkSize];
offset += [chunk length];
NSString *base64EncodedChunkString = [chunk base64EncodedString];
NSData *base64EncodedChunk = [base64EncodedChunkString dataUsingEncoding:NSASCIIStringEncoding];
[encodedFile writeData:base64EncodedChunk];
base64EncodedChunkString = nil;
base64EncodedChunk = nil;
} while (offset < length);
我希望我能把功劳归功于 GregInYEG,因为他关于填充的最初观点是根本问题。使用 base64,每个块必须是 3 的倍数。因此这解决了问题:
chunkSize = 3600
Run Code Online (Sandbox Code Playgroud)
一旦我有了这个,腐败就消失了。但后来我遇到了内存泄漏问题,所以我添加了从这篇文章中获取的自动释放池方法:http://www.cocoadev.com/index.pl?ReadAFilePieceByPiece
最终代码:
// Read data in chunks from the original file
[originalFile seekToEndOfFile];
NSUInteger fileLength = [originalFile offsetInFile];
[originalFile seekToFileOffset:0];
// For base64, each chunk *MUST* be a multiple of 3
NSUInteger chunkSize = 24000;
NSUInteger offset = 0;
NSAutoreleasePool *chunkPool = [[NSAutoreleasePool alloc] init];
while(offset < fileLength) {
// Read the next chunk from the input file
[originalFile seekToFileOffset:offset];
NSData *chunk = [originalFile readDataOfLength:chunkSize];
// Update our offset
offset += chunkSize;
// Base64 encode the input chunk
NSData *serializedChunk = [NSPropertyListSerialization dataFromPropertyList:chunk format:NSPropertyListXMLFormat_v1_0 errorDescription:NULL];
NSString *serializedString = [[NSString alloc] initWithData:serializedChunk encoding:NSASCIIStringEncoding];
NSRange r = [serializedString rangeOfString:@"<data>"];
serializedString = [serializedString substringFromIndex:r.location+7];
r = [serializedString rangeOfString:@"</data>"];
serializedString = [serializedString substringToIndex:r.location-1];
// Write the base64 encoded chunk to our output file
NSData *base64EncodedChunk = [serializedString dataUsingEncoding:NSASCIIStringEncoding];
[encodedFile truncateFileAtOffset:[encodedFile seekToEndOfFile]];
[encodedFile writeData:base64EncodedChunk];
// Cleanup
base64EncodedChunk = nil;
serializedChunk = nil;
serializedString = nil;
chunk = nil;
// Update the progress bar
[self updateProgress:[NSNumber numberWithInt:offset] total:[NSNumber numberWithInt:fileLength]];
// Drain and recreate the pool
[chunkPool release];
chunkPool = [[NSAutoreleasePool alloc] init];
}
[chunkPool release];
Run Code Online (Sandbox Code Playgroud)