2010-10-04 2 views
8

Update 4
предложения Per Грега Я создал одну пару изображений/текста, который показывает выход из 37k изображений в base64 кодированного, используя 100k ломтей. Так как файл всего 37k, можно с уверенностью сказать, что цикл повторяется только один раз, поэтому ничего не было добавлено. Другая пара показывает результат с одного и того же изображения 37k на base64, с использованием 10k кусков. Так как файл равен 37k, цикл повторяется четыре раза, и данные были определенно добавлены.Base64 Encode файл Использование NSData Куски

Выполнение диф на двух файлов показывает, что в файле 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]]; 
} 

Update 2
Так это выглядит как файлы, размер которых превышает 100 КБ получить яичницу, но файлы в 100 килобайт в порядке. Очевидно, что что-то отключено в моем буфере/математике/и т. Д., Но я потерялся на этом. Возможно, настало время назвать это днем, но я бы с удовольствием заснул с этим решением.

Вот пример:

Update 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); 
+0

Каким образом испорченный выход? – Greg

+0

Для изображений (JPEG) и видео (Quicktime) файлы не читаются. – frsh

+0

Что побуждает меня поверить, что что-то не так с моим смещением. Когда я использую ту же категорию base64 в NSData, не разбивая ее на куски, она работает нормально. – frsh

ответ

2

Хотелось бы, чтобы я мог отдать должное GregInYEG, потому что его первоначальная точка прополнения была основной проблемой. С base64, каждый кусок должен быть кратно 3. Таким образом, этот вопрос решен:

chunkSize = 3600 

После того, как у меня было, что порча ушла.Но тогда я столкнулся с проблемами утечки памяти, поэтому я добавил autorelease бассейна apprach, взятый из этого поста: 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]; 
+0

Hey @frsh ... Спасибо за сообщение ответа, но код выглядит неполным (особенно цикл while) ... можете ли вы отправить полный код, если сможете ... Спасибо ... –

1

Как вы преобразования данных обратно base64 к изображению? Некоторые реализации ограничивают максимальную длину линии, которую они будут принимать. Попробуйте вставить разрыв строки каждый так много символов.

+0

Просто попробовал добавить новую строку для каждого цикла, но это не повлияло. – frsh

+0

Но каждая итерация в вашей петле длиннее 25 000 символов! Попробуйте что-то вроде 80 символов в строке. – Aleph7

+0

OK, просто попробовал добавить новую строку каждые 80 символов и получил тот же результат. Спасибо за предложение! – frsh