更新 4
Greg の提案に従って、100k チャンクを使用して、37k 画像から base64 エンコードへの出力を示す画像/テキストのペアを 1 つ作成しました。ファイルはわずか 37k であるため、ループは 1 回だけ繰り返され、何も追加されなかったと言っても過言ではありません。もう 1 つのペアは、10k チャンクを使用して base64 でエンコードされた、同じ 37k 画像からの出力を示しています。ファイルは 37k であるため、ループは 4 回繰り返され、データは確実に追加されました。
2 つのファイルの diff を実行すると、10kb のチャンク ファイルでは、214 行目から 640 行目までに大きな違いがあることがわかります。
- 小さな画像 (37k) - 100k チャンク - 画像出力
- 小さな画像 (37k) - 100k チャンク - Base64 テキスト出力
- 小さな画像 (37k) - 10k チャンク - 画像出力
- 小さな画像 (37k) - 10k チャンク - Base64 テキスト出力
更新 3
これが私のコードの現在の場所です。少しクリーンアップしましたが、それでも同じ効果が得られます:
// 元のファイルからチャンク単位でデータを読み取ります [originalFile seekToEndOfFile]; NSUInteger fileLength = [originalFile offsetInFile]; [originalFile seekToFileOffset:0]; NSUInteger チャンクサイズ = 100 * 1024; NSUInteger オフセット = 0; while(オフセット < ファイル長) { 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]]; }
Update 2
つまり、100 KB を超えるファイルはスクランブルされるように見えますが、100 KB 未満のファイルは問題ありません。私のバッファ/数学/その他で何かがずれていることは明らかですが、これについては迷っています。もう終わりかもしれませんが、この問題を解決して眠りたいです。
次に例を示します。
更新 1
いくつかのテストを行った後、同じコードが小さな画像では正常に機能することがわかりましたが、大きな画像や任意のサイズのビデオでは機能しません。間違いなくバッファの問題のようですね。
やあ、大きなファイルを base64 でエンコードしようとして、一度に 1 つの小さなチャンクをループして実行しようとしています。すべてが機能しているように見えますが、ファイルは常に破損してしまいます。ここで私が間違っている可能性がある場所を誰かが指摘できるかどうか、私は興味がありました:
NSFileHandle *originalFile, *encodedFile; self.localEncodedURL = [NSString stringWithFormat:@"%@-base64.xml", self.localURL]; // 元のファイルを読み取り用に開く originalFile = [NSFileHandle fileHandleForReadingAtPath:self.localURL]; if (originalFile == nil) { [self performSelectorOnMainThread:@selector(updateStatus:) withObject:@"エンコードに失敗しました。" waitUntilDone:いいえ]; 戻る; } encodedFile = [NSFileHandle fileHandleForWritingAtPath:self.localEncodedURL]; if (encodedFile == nil) { [self performSelectorOnMainThread:@selector(updateStatus:) withObject:@"エンコードに失敗しました。" waitUntilDone:いいえ]; 戻る; } // 元のファイルからチャンク単位でデータを読み取ります [originalFile seekToEndOfFile]; NSUInteger の長さ = [originalFile offsetInFile]; [originalFile seekToFileOffset:0]; NSUInteger チャンクサイズ = 100 * 1024; NSUInteger オフセット = 0; 行う { NSUInteger thisChunkSize = 長さ - オフセット > チャンクサイズ ? chunkSize : 長さ - オフセット; NSData *chunk = [originalFile readDataOfLength:thisChunkSize]; オフセット += [チャンク長]; NSString *base64EncodedChunkString = [チャンク base64EncodedString]; NSData *base64EncodedChunk = [base64EncodedChunkString dataUsingEncoding:NSASCIIStringEncoding]; [encodedFile writeData:base64EncodedChunk]; base64EncodedChunkString = nil; base64EncodedChunk = nil; while (オフセット < 長さ);