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.

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:
condotto da imgur.com

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);
È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top