Got wrong value while detecting available disk space on iphone - iphone

I follow http://kdbdallas.com/2008/12/27/maciphone-show-availble-useable-diskspace/
and how do i find out iphone Disk Space?
to detect the available disk space. However, seem that the result is not correct
I tested on iphone 4 ios 4.2.1.
in Setting,
Capacity is 29.1 G
Availability is 24.2 G
I want to get 24.2 G value. So I followed the tutorial I mentioned above.
int main(int argc, char *argv[]) {
.....
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSLog(#"path %#", paths);
struct statfs tStats;
statfs([[paths lastObject] UTF8String], &tStats);
NSString *sizeType;
float total_space = (float)(tStats.f_blocks * tStats.f_bsize);
NSLog(#"total space: %f", total_space);
NSLog(#"total space: %#", convertUnit(total_space));
float free_space = (float)(tStats.f_bfree * tStats.f_bsize);
NSLog(#"free space: %f", free_space);
NSLog(#"free space: %#", convertUnit(free_space));
float free_space2 = (float)(tStats.f_bavail * tStats.f_bsize);
NSLog(#"free blocks avail to non-superuser: %f", free_space2);
NSLog(#"free blocks avail to non-superuser: %#", convertUnit(free_space2));
uint32_t block_size = (tStats.f_bsize);
NSLog(#"block size: %d", block_size);
NSLog(#"block size: %#", convertUnit(block_size));
.....
}
NSString* convertUnit (float value) {
NSString *sizeType;
if (value > 1024)
{
//Kilobytes
value = value / 1024;
sizeType = #" KB";
}
if (value > 1024)
{
//Megabytes
value = value / 1024;
sizeType = #" MB";
}
if (value > 1024)
{
//Gigabytes
value = value / 1024;
sizeType = #" GB";
}
return [[#"Available Disk Space: " stringByAppendingFormat:#"%.2f", value] stringByAppendingString:sizeType];
}
RESULT:
total space: 17363854862722269184.000000
total space: Available Disk Space: 16171350016.00 GB
free space: 17743592094095638528.000000
free space: Available Disk Space: 16525007872.00 GB
free blocks avail to non-superuser: 17432956969504735232.00000
free blocks avail to non-superuser: Available Disk Space: 16235706368.00 GB
block size: 803203484
block size: Available Disk Space: 765.99 MB

After do more search about file system of iphone, I found that iphone has 2 partitions: one for os and another for user data. The values I got is the attributes of OS partitions. So I changed the path to be 'private/var' which is the path of data partition. As a result, I got the correct value for free disk space.

Try this code
-(uint64_t)getFreeDiskspace {
uint64_t totalSpace = 0;
uint64_t totalFreeSpace = 0;
NSError *error = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] error: &error];
if (dictionary) {
NSNumber *fileSystemSizeInBytes = [dictionary objectForKey: NSFileSystemSize];
NSNumber *freeFileSystemSizeInBytes = [dictionary objectForKey:NSFileSystemFreeSize];
totalSpace = [fileSystemSizeInBytes unsignedLongLongValue];
totalFreeSpace = [freeFileSystemSizeInBytes unsignedLongLongValue];
NSLog(#"Memory Capacity of %llu MiB with %llu MiB Free memory available.", ((totalSpace/1024ll)/1024ll), ((totalFreeSpace/1024ll)/1024ll));
} else {
NSLog(#"Error Obtaining System Memory Info: Domain = %#, Code = %#", [error domain], [error code]);
}
return ((totalFreeSpace/1024ll)/1024ll);
}
This will give you total free Space in MB

Related

Compress Large UIImage

so what im doing is compressing an image repeatedly until it fits within a size frame. It it takes to many attempts, give up and later we tell the user the image is to large.
My issue is that after the image size has been reduced, its size goes WAY back up again when its changed to a UIImage.
Here is the code for reducing the image size:
double compressionRatio = 1;
int resizeAttempts = 5;
NSData * imgData = UIImageJPEGRepresentation([info objectForKey:#"UIImagePickerControllerOriginalImage"],compressionRatio);
NSLog(#"Starting Size: %i", [imgData length]);
//Trying to push it below around about 0.4 meg
while ([imgData length] > 400000 && resizeAttempts > 0) {
resizeAttempts -= 1;
NSLog(#"Image was bigger than 400000 Bytes. Resizing.");
NSLog(#"%i Attempts Remaining",resizeAttempts);
//Increase the compression amount
compressionRatio = compressionRatio*0.5;
//Test size before compression
NSLog(#"Current Size: %i",[imgData length]);
imgData = UIImageJPEGRepresentation([info objectForKey:#"UIImagePickerControllerOriginalImage"],compressionRatio);
//Test size after compression
NSLog(#"New Size: %i",[imgData length]);
}
//Set image by comprssed version
savedImage = [UIImage imageWithData:imgData];
//Check how big the image is now its been compressed and put into the UIImageView
NSData *endData = UIImageJPEGRepresentation(savedImage,1.0);
NSLog(#"Ending Size: %i", [endData length]);
Ok now here is the console report:
Starting Image Size: 4076994
Image was bigger than 400000 Bytes. Resizing.
4 Attempts Remaining
Current Size: 4076994
New Compressed Size: 844482
Image was bigger than 400000 Bytes. Resizing.
3 Attempts Remaining
Current Size: 844482
New Compressed Size: 357459
Ending Image Size: 2090332
As you can see the image started at 4mb big. It was compressed to 350kb, then in the end it was made into a UIImage as 2mb.
Thanks in advance to anyone who can make any sense of this.
I have modified your function a bit and got result, try it, it reduce my 10MB image to 3MB.
-(void)compraseImage
{
UIImage *largeImage = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
double compressionRatio = 1;
int resizeAttempts = 5;
NSData * imgData = UIImageJPEGRepresentation(largeImage,compressionRatio);
NSLog(#"Starting Size: %i", [imgData length]);
//Trying to push it below around about 0.4 meg
while ([imgData length] > 400000 && resizeAttempts > 0) {
resizeAttempts -= 1;
NSLog(#"Image was bigger than 400000 Bytes. Resizing.");
NSLog(#"%i Attempts Remaining",resizeAttempts);
//Increase the compression amount
compressionRatio = compressionRatio*0.5;
NSLog(#"compressionRatio %f",compressionRatio);
//Test size before compression
NSLog(#"Current Size: %i",[imgData length]);
imgData = UIImageJPEGRepresentation(largeImage,compressionRatio);
//Test size after compression
NSLog(#"New Size: %i",[imgData length]);
}
//Set image by comprssed version
savedImage = [UIImage imageWithData:imgData];
//Check how big the image is now its been compressed and put into the UIImageView
// *** I made Change here, you were again storing it with Highest Resolution ***
NSData *endData = UIImageJPEGRepresentation(largeImage,compressionRatio);
NSLog(#"Ending Size: %i", [endData length]);
NSString *path = [self createPath:#"myImage.jpg"];
NSLog(#"%#",path);
[endData writeToFile:path atomically:YES];
}
-(NSString *) createPath:(NSString *)withFileName
{
NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,
YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:withFileName];
return path;
}

ALAssets get video data

I am trying to access video data from ALAssets library using the below code
ALAssetRepresentation *rep = [asset defaultRepresentation];
Byte *buffer = (Byte*)malloc(rep.size);
NSError *error = nil;
NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:rep.size error:&error];
NSData *data = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];
It works fine for small video as well as pictures, But if am trying to get a large video, the code crashes saying
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[NSConcreteData initWithBytes:length:copy:freeWhenDone:bytesAreVM:]: absurd length: 4294967295, maximum size: 2147483648 bytes'
I don't have an idea what's going on. Any one any thoughts?
Thanks in advance!
I found the solution. I guess the crash may be due to huge memory spike when we upload large files, because I am buffering data. Now I read file data as 5 MB chunks and this fix the crash. I am pasting my code below.
- (NSData *)getDataPartAtOffset:(NSInteger)offset {
__block NSData *chunkData = nil;
if (fileAsset_){
static const NSUInteger BufferSize = PART_SIZE; // 5 MB chunk
ALAssetRepresentation *rep = [fileAsset_ defaultRepresentation];
uint8_t *buffer = calloc(BufferSize, sizeof(*buffer));
NSUInteger bytesRead = 0;
NSError *error = nil;
#try
{
bytesRead = [rep getBytes:buffer fromOffset:offset length:BufferSize error:&error];
chunkData = [NSData dataWithData:[NSData dataWithBytesNoCopy:buffer length:bytesRead freeWhenDone:NO]];
}
#catch (NSException *exception)
{
free(buffer);
chunkData = nil;
// Handle the exception here...
}
free(buffer);
} else {
NSLog(#"failed to retrive Asset");
}
return chunkData;
}
And I I'll call this function as
int offset = 0; // offset that keep tracks of chunk data
do {
#autoreleasepool {
NSData *chunkData = [self getDataPartAtOffset:offset];;
if (!chunkData || ![chunkData length]) { // finished reading data
break;
}
// do your stuff here
offset +=[chunkData length];
}
} while (1);
chilitechno's bit here worked for me.

large number of large files creating leak while creating zip file

NSData * buffer = [fileHandle readDataOfLength:chunkSize];
while ([buffer length] > 0)
{
[streamBIG writeData:buffer];
offset += [buffer length];
[fileHandle seekToFileOffset:offset];
buffer = [fileHandle readDataOfLength:chunkSize];
}
I use these particular process to zip more then 1 file of 25 - 30 MB but these increases memory i.e. live bytes continuously increase till all files are not written, because of which my app crashes
Try like this with Auto release pool
NSData * buffer = [fileHandle readDataOfLength:chunkSize];
while ([buffer length] > 0)
{
#autoreleasepool
{
[streamBIG writeData:buffer];
offset += [buffer length];
[fileHandle seekToFileOffset:offset];
buffer = [fileHandle readDataOfLength:chunkSize];
}
}
it will work...

Issue With selecting multiple images

How to detect total available/free disk space on the iPhone/iPad device?
I assume that clicking that "done" button would invoke cancelling the picker; in which case you can try did you try implementing the delegate method:
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[self dismissViewControllerAnimated:YES completion:^(void) {
NSLog(#"Cancelled pick");
};
}
Also it looks like you're calling release -- any reason you're not using ARC?
If I had to guess, I'd say perhaps the alert dismiss is in fact calling something like
[imagePicker.delegate imagePickerControllerDidCancel:imagePicker];
but it's already released so you're seeing this "lock-up" issue. Maybe step through in the debugger and make sure those objects still exist.
Edit:
While it doesn't solve your original issue, you could do a check for available space prior to launching the image picker, possibly with something like this so post suggests:
- (uint64_t)freeDiskspace
{
uint64_t totalSpace = 0;
uint64_t totalFreeSpace = 0;
__autoreleasing NSError *error = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] error: &error];
if (dictionary) {
NSNumber *fileSystemSizeInBytes = [dictionary objectForKey: NSFileSystemSize];
NSNumber *freeFileSystemSizeInBytes = [dictionary objectForKey:NSFileSystemFreeSize];
totalSpace = [fileSystemSizeInBytes unsignedLongLongValue];
totalFreeSpace = [freeFileSystemSizeInBytes unsignedLongLongValue];
NSLog(#"Memory Capacity of %llu MiB with %llu MiB Free memory available.", ((totalSpace/1024ll)/1024ll), ((totalFreeSpace/1024ll)/1024ll));
} else {
NSLog(#"Error Obtaining System Memory Info: Domain = %#, Code = %d", [error domain], [error code]);
}
return totalFreeSpace;
}

Getting wrong available memory of ipad?

I am getting available memory from below method:
static void print_free_memory () {
float totalSpace = 0.0f;
NSError *error = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] error: &error];
if (dictionary) {
NSNumber *fileSystemSizeInBytes = [dictionary objectForKey: NSFileSystemSize];
totalSpace = [fileSystemSizeInBytes floatValue];
NSLog(#"Total memory:%f",totalSpace);
freeMemAvailable = [[dictionary objectForKey:NSFileSystemFreeSize] floatValue];
NSLog(#"Free Memory:%f",freeMemAvailable);
} else {
NSLog(#"Error Obtaining File System Info: Domain = %#, Code = %#", [error domain], [error code]);
}
}
Above method returns = 9139.650391 mb ~ 9.14 GB
AND on Device memory displayed on the Device = 8.4 GB
Approximately, 700 MB difference. Why is it so? Any suggestions.
The path that I used to view the device memory on device is as follows.
Go to :- Settings -> General -> About -> Available
Your calculations are not precise the function return the size in bytes so assume the returned value was 9139650391 you will need to divide it bu (1024*1024*1024) = 1073741824
so 9139650391/1073741824 equals approximately 8.5 GB and not 9.14 GB
about the 100 MB difference, there is still a difference but not as big as 700MB