how compress large file?
Closed this issue · 6 comments
` [newArchive updateEntries: @[//[ZZArchiveEntry archiveEntryWithDirectoryName:@"/"],
[ZZArchiveEntry archiveEntryWithFileName:@"insert.zip"
compress:YES
streamBlock:^BOOL(NSOutputStream output, NSError* error)
{
// output = [[NSOutputStream alloc]initToFileAtPath:[docDir stringByAppendingPathComponent:@"tmpout"] append:NO];
NSInputStream *inputStream = [[NSInputStream alloc] initWithFileAtPath: insertfile];
[inputStream open];
NSInteger maxLength = 1024;
uint8_t readBuffer [maxLength];
//是否已经到结尾标识
BOOL endOfStreamReached = NO;
NSInteger bytesRead = 0;
NSInteger bytesWrite = 0;
// NOTE: this tight loop will block until stream ends
while (! endOfStreamReached)
{
bytesRead = [inputStream read: readBuffer maxLength:maxLength];
if (bytesRead == 0)
{//文件读取到最后
endOfStreamReached = YES;
}
else if (bytesRead == -1)
{//文件读取错误
endOfStreamReached = YES;
}
else
{
//this will boom the memory!!!!!!!!
** bytesWrite = [output write:readBuffer maxLength:bytesRead];**
if (bytesWrite == -1) {
return NO;
}
}
}
[inputStream close];
return YES; }]
]
error:&err];`
if I wanna compress a large file > 512MB. I think I should use the stream.
but the streamblock need NSOutputStream, not inputstream.
I don't know how to send the file data.
Please help , thank you!
//this will boom the memory!!!!!!!!
bytesWrite = [output write:readBuffer maxLength:bytesRead];
- (NSData_)newInput:(out NSError_*)error
{
return [[NSData alloc] initWithContentsOfURL:_URL
options:NSDataReadingMappedAlways
error:error];
}
bull shit!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1_
http://stackoverflow.com/questions/8928723/how-can-i-read-a-large-utf-8-file-on-an-iphone
2_
` @autoreleasepool{
uLong maxLength = deflateBound(&_stream, length);
NSMutableData* outputBuffer = [[NSMutableData alloc] initWithLength:maxLength];
// deflate buffer to output buffer
_stream.next_in = (Bytef*)buffer;
_stream.avail_in = (uInt)length;
_stream.next_out = (Bytef*)outputBuffer.mutableBytes;
_stream.avail_out = (uInt)maxLength;
deflate(&_stream, Z_NO_FLUSH);
// write out deflated output if any
outputBuffer.length = maxLength - _stream.avail_out;
if (outputBuffer.length > 0)
{
NSError* __autoreleasing writeError;
if (![_channelOutput writeData:outputBuffer
error:&writeError])
{
_status = NSStreamStatusError;
_error = writeError;
return -1;
}
}
}
`
@autoreleasepool the every write event. ARC not immediate??????
I want to add a _outputBuffer in the init function of the ZZDeflateOutputStream class.
but if I fix lenght of alloc memory, compress file will wrong.
To write large file entries, you can either use the stream or the data initializer.
If you use the stream initializer, you'll need to buffer input from your input stream and then write it out the output stream, as you have coded. bytesWrite = [output write:readBuffer maxLength:bytesRead];
seems correct, what's wrong with it?
Note that [output write:readBuffer maxLength:bytesRead]
is not guaranteed to write out all the bytes; if it doesn't, you'll need to loop until it writes out everything. Something like ZZZipNewTests.m:76.
If you use the data initializer instead, you should be able to use the data initializer with NSDataReadingMappedAlways
option as you've listed. If the data is memory mapped this should be more efficient than using the stream since the compressor can see the entire file at once.
Yeah, I got it!
very thanks.
but in your project ,
@autoreleasepool{...}
should be join the write method.
The method will always alloc the memory when called.
And, ARC can't Immediate release the memory when method end.
So,
for (bytes = (const uint8_t*)data.bytes, bytesLeft = data.length; bytesLeft > 0; bytes += bytesWritten, bytesLeft -= bytesWritten) { bytesWritten = [output write:bytes maxLength:MIN(bytesLeft, 1024)]; if (bytesWritten == -1) { if (error) *error = output.streamError; return NO; } } return YES; }] ]
it will malloc(((data.length)/1024) * 1024), too large more then the openfile.
Thank you, thanks for your work!
Good day