Saving and loading RawString with compression

Discussion and help for Easy Save 3
Post Reply
erlemaitre
Posts: 8
Joined: Fri Jan 08, 2021 11:44 am

Saving and loading RawString with compression

Post by erlemaitre »

Hello,

I was wondering if it's possible to combine compression with saving/loading as RawString ? :geek:

I need to save and load from ES3 as RawString (or RawBytes, if necessary), to send and load the data to an iOS Plugin. For now, I'm only using saving as RawString, and sending that string to my plugin, but I would like to be able to compress this data.

What would be the best way to compress and then send that data to my plugin ?
User avatar
Joel
Moodkie Staff
Posts: 4846
Joined: Wed Nov 07, 2012 10:32 pm

Re: Saving and loading RawString with compression

Post by Joel »

Hi there,

You can provide an ES3Settings object with compression enabled to the SaveRaw/LoadRawString methods, as described in the Compression guide:
https://docs.moodkie.com/easy-save-3/es ... mpression/

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
erlemaitre
Posts: 8
Joined: Fri Jan 08, 2021 11:44 am

Re: Saving and loading RawString with compression

Post by erlemaitre »

I tried using these settings, but I can't get it working on a real device (iOS). Saving throws no error, but when I try to load the file, I get the following error : FormatException: Cannot load from file because the data in it is not JSON data, or the data is encrypted.

My code in C# is the following :

Code: Select all

public void SaveCubes(GameObject[] cubes) {
    var settings = new ES3Settings(ES3.Location.Cache, ES3.CompressionType.Gzip);
    ES3.Save("cubes", cubes, settings);

    string rawString = ES3.LoadRawString(settings);
    iOSPlugin.SaveRawString(rawString);
}

public void LoadCubes(GameObject[] cubes) {
    var rawString = iOSPlugin.LoadRawString();
    var settings = new ES3Settings(ES3.Location.Cache, ES3.CompressionType.Gzip);

    ES3.SaveRaw(rawString, settings);
    ES3.LoadInto("cubes", cubes, settings);
}
Then, this data is sent to my iOS plugin, transformed to a NSData object, and written to a file. And for loading, I read the file, extract the string, and send it to C#.

My Objective-C code looks like this :

Code: Select all

+(void)saveRawString:(const char*)rawString {
    NSString *appSupportDir = [NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) lastObject];
    //If there isn't an App Support Directory yet ...
    if (![[NSFileManager defaultManager] fileExistsAtPath:appSupportDir isDirectory:NULL]) {
        NSError *error = nil;
        //Create one
        if (![[NSFileManager defaultManager] createDirectoryAtPath:appSupportDir withIntermediateDirectories:YES attributes:nil error:&error]) {
            NSLog(@"%@", error.localizedDescription);
        }
        else {
            // Mark the directory as excluded from iCloud backups
            NSURL *url = [NSURL fileURLWithPath:appSupportDir];
            if (![url setResourceValue:@YES
                                forKey:NSURLIsExcludedFromBackupKey
                                 error:&error])
            {
                NSLog(@"Error excluding %@ from backup %@", url.lastPathComponent, error.localizedDescription);
            }
            else {
                NSLog(@"Yay");
            }
        }
    }
    
    NSString *saveString = [NSString stringWithUTF8String:rawString];
    NSData *data = [saveString dataUsingEncoding:NSUTF8StringEncoding];
    
    // Generate the file path
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"gameData.es3"];
    
    // Save it into file system
    [data writeToFile:dataPath atomically:YES];
}

+(const char*)loadRawString {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = paths.firstObject;
    NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"gameData.es3"];
    
    NSData *data = [NSData dataWithContentsOfFile:dataPath];
    NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    return [string UTF8String];
}
I don't know what causes this issue, but I know that without compression, it works perfectly fine.
Thank you,
Eric
User avatar
Joel
Moodkie Staff
Posts: 4846
Joined: Wed Nov 07, 2012 10:32 pm

Re: Saving and loading RawString with compression

Post by Joel »

Hi Eric,

Unfortunately I wouldn't be able to assist with your custom code. However, you might want to check that the data being returned from the iOS plugin is the same as the data returned by the ES3.LoadRawString method before you saved it.

What I suspect is happening is that when the plugin applies an encoding, it corrupts the data. If this is the case then you would need to use ES3.LoadRawBytes, and then convert these bytes to a Base-64 string. Then when you get your data back from the plugin, convert it from a Base-64 string back to a byte array.

Just to check, is there any reason you're sending the data to an iOS plugin to be saved rather than getting Easy Save to store the data?

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
erlemaitre
Posts: 8
Joined: Fri Jan 08, 2021 11:44 am

Re: Saving and loading RawString with compression

Post by erlemaitre »

Hi Joel,

Actually, the issue was in my C# code, when I load the string. I was using ES3.SaveRaw(), but with the compression setting, so basically, I was compressing an already compressed file, and that's why the load method could not work.

And I just realized that it's in my plugin that I should compress the raw string, because I'm always sending and loading strings from and to iOS, rather than sending and receiving compressed files :shock:

I want to upload the data to iCloud, that's the reason for using a native plugin.

Thank you for your help! :)
Best regards,
Eric
Post Reply