File Base64 Codifica Utilizzando NSData Bocconcini
-
27-09-2019 - |
Domanda
Aggiorna 4
Per suggerimento di Greg Ho creato un paio di immagine / testo che mostra l'uscita da un'immagine 37k a Base64 codificati, utilizzando 100k pezzi. Dal momento che il file è solo 37k è sicuro di dire che il ciclo sola volta iterato, quindi nulla è stato aggiunto. Gli altri spettacoli pair l'uscita dalla stessa immagine 37k a base64 codificato utilizzando 10k blocchi. Dal momento che il file è 37k l'anello iterata quattro volte, e dati sono stati sicuramente aggiunto.
Facendo un diff sui file due spettacoli che sul file 10kb pezzo c'è una grande differenza che inizia sulla linea 214 e termina sulla linea 640.
- Immagine piccola (37k) - 100k - Bocconcini uscita immagine
- Immagine piccola (37k) - 100k Chunks - uscita Base64 Testo
- Immagine piccola (37k) - 10k Chunks - uscita immagine
- Immagine piccola (37k) - 10k Chunks - uscita Base64 Testo
Aggiorna 3
Qui è dove il mio codice è ora. Ripulito un po ', ma continua a produrre lo stesso effetto:
// 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]]; }
Aggiorna 2
Quindi sembra che i file di dimensioni superiori a 100 KB vengono strapazzate, ma i file meno di 100 KB vanno bene. E 'ovvio che qualcosa è fuori sul mio tampone / math / etc, ma mi sono perso su questo. Potrebbe essere il momento di chiamare un giorno, ma mi piacerebbe andare a dormire con questo risolto.
Ecco un esempio:
Aggiorna 1
Dopo aver fatto qualche test ho trovato che lo stesso codice funziona bene per una piccola immagine, ma non funziona per una grande immagine o un video di qualsiasi dimensione. sembra decisamente come un problema di buffer, giusto?
Hey there, cercando di base64 codificare un file di grandi dimensioni da loop attraverso e facendo un piccolo pezzo alla volta. Tutto sembra funzionare ma i file finiscono sempre per corrotti. Ero curioso di sapere se qualcuno potesse indicare dove potrei andare male qui:
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);
Soluzione
vorrei poter dare credito a GregInYEG, perché il suo punto originale sulla imbottitura era la questione di fondo. Con Base64, ogni blocco deve essere un multiplo di 3. Quindi questo ha risolto il problema:
chunkSize = 3600
Una volta che ho avuto, la corruzione è andato via. Ma poi mi sono imbattuto in problemi di perdita di memoria, così ho aggiunto la piscina autorelease apprach preso da questo post: http://www.cocoadev.com/index.pl?ReadAFilePieceByPiece
codice finale:
// 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];
Altri suggerimenti
Come stai riconversione dei dati base64 a un'immagine? Alcune implementazioni limitano la lunghezza massima della linea sono disposti ad accettare. Prova l'inserimento di una linea di pausa ogni tanti personaggi.