Arian Faurtosh
Arian Faurtosh

Reputation: 18511

How to check to see if same exact file exists

I am currently using this code to copy my SQLite database, however it is currently only checking to see if the file exists... I want to change it to check if the file isn't exactly the same, for example I am worried if a database gets corrupt or doesn't copy all the way, the app will lose functionality and the only way to fix this would be to delete the App and redownload it.

So how can I compare if two files are exactly equal?

- (void) copyDatabaseIfNeeded {


    //Using NSFileManager we can perform many file system operations.
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error;

    NSString *dbPath = [self getDBPath];
    BOOL success = [fileManager fileExistsAtPath:dbPath];

    //NSLog(@"%d",success);

    if(!success) {

        NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"database01.sqlite"];
        success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];

        if (!success)
            NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);
    }
}

- (NSString *) getDBPath
{
    //Search for standard documents using NSSearchPathForDirectoriesInDomains
    //First Param = Searching the documents directory
    //Second Param = Searching the Users directory and not the System
    //Expand any tildes and identify home directories.

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
    NSString *documentsDir = [paths objectAtIndex:0];
    //NSLog(@"dbpath : %@",documentsDir);
    return [documentsDir stringByAppendingPathComponent:@"database01.sqlite"];
}

Upvotes: 1

Views: 438

Answers (2)

rmaddy
rmaddy

Reputation: 318794

Edit - Forget this answer - use the one by Ayan.

Start by comparing the file sizes. If the sizes are different you know the files are not the same. This is a simple and quick check.

If the sizes are the same then you need to compare the files, byte by byte. An inefficient way would be to load both files into NSData objects and see if they are equal. This only works if the files will always be small enough to fit in memory.

A better approach is to open both files as streams and read them in chunks. Compare each chunk (say 2k each) until two chunks are different or you get to the end.

Upvotes: 1

Ayan Sengupta
Ayan Sengupta

Reputation: 5386

You can use contentsEqualAtPath:andPath: method of NSFileManager for this purpose. Use your code something like this:

......
if(!success) {
    NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"database01.sqlite"];
    success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];

    if (!success)
        NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);

   success = [fileManager contentsEqualAtPath:defaultDBPath andPath:dbPath]; //verify if file size and content matches
    if(!success) {
        //report error
    }
}
.......

And it should do the trick for you.

Upvotes: 4

Related Questions