8

更新 4
根据 Greg 的建议,我创建了一对图像/文本,使用 100k 块显示从 37k 图像到 base64 编码的输出。由于文件只有 37k,可以肯定地说循环只迭代了一次,所以没有附加任何内容。另一对使用 10k 块显示从相同 37k 图像到 base64 编码的输出。由于文件为 37k,因此循环迭代了四次,并且肯定附加了数据。

对这两个文件进行比较表明,在 10kb 的块文件上,从第 214 行开始到第 640 行结束的差异很大。

更新 3
这是我的代码现在所在的位置。清理了一下,但仍然产生相同的效果:

// 从原始文件中分块读取数据
[原始文件 seekToEndOfFile];
NSUInteger fileLength = [originalFile offsetInFile];
[原始文件 seekToFileOffset:0];
NSUInteger 块大小 = 100 * 1024;
NSUInteger 偏移量 = 0;

而(偏移量<文件长度){
    NSData *chunk = [originalFile readDataOfLength:chunkSize];
    偏移量 += 块大小;

    // 将块转换为 base64 编码的字符串并返回到 NSData
    NSString *base64EncodedChunkString = [块 base64EncodedString];
    NSData *base64EncodedChunk = [base64EncodedChunkString dataUsingEncoding:NSASCIIStringEncoding];

    // 将编码后的块写入我们的输出文件
    [encodedFile writeData:base64EncodedChunk];

    // 清理
    base64EncodedChunkString = nil;
    base64EncodedChunk = nil;

    // 更新进度条
    [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];

    // 打开原始文件进行读取
    originalFile = [NSFileHandle fileHandleForReadingAtPath:self.localURL];
    if (originalFile == nil) {
        [self performSelectorOnMainThread:@selector(updateStatus:) withObject:@"编码失败。" 等待直到完成:否];
        返回;
    }
    encodedFile = [NSFileHandle fileHandleForWritingAtPath:self.localEncodedURL];
    if (encodedFile == nil) {
        [self performSelectorOnMainThread:@selector(updateStatus:) withObject:@"编码失败。" 等待直到完成:否];
        返回;
    }

    // 从原始文件中分块读取数据
    [原始文件 seekToEndOfFile];
    NSUInteger 长度 = [originalFile offsetInFile];
    [原始文件 seekToFileOffset:0];
    NSUInteger 块大小 = 100 * 1024;
    NSUInteger 偏移量 = 0;
    做 {
        NSUInteger thisChunkSize = 长度 - 偏移 > chunkSize ?chunkSize : 长度 - 偏移量;
        NSData *chunk = [originalFile readDataOfLength:thisChunkSize];
        偏移 += [块长度];

        NSString *base64EncodedChunkString = [块 base64EncodedString];
        NSData *base64EncodedChunk = [base64EncodedChunkString dataUsingEncoding:NSASCIIStringEncoding];

        [encodedFile writeData:base64EncodedChunk];

        base64EncodedChunkString = nil;
        base64EncodedChunk = nil;

    } 而(偏移量 < 长度);
4

2 回答 2

2

我希望我可以赞扬 GregInYEG,因为他关于填充的最初观点是根本问题。使用 base64,每个块必须是 3 的倍数。所以这解决了这个问题:

chunkSize = 3600

一旦我有了它,腐败就消失了。但后来我遇到了内存泄漏问题,所以我添加了从这篇文章中获取的自动释放池方法: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];
于 2010-10-06T14:17:26.897 回答
1

您如何将 base64 数据转换回图像?一些实现限制了它们将接受的最大行长度。尝试每隔这么多字符插入一个换行符。

于 2010-10-05T02:37:34.043 回答