Okay, so I was bothering quite some time “How to save large amount of data locally and load it later?”
Forums and answers helped me quite a lot and I learned much about serialization and such and as I discovered new methods choices began to appear.
I’m creating large 2D world that need to be saved/loaded and I decided to use text saving because its faster than XML and smaller than XML, and because i don’t want player to edit save files so easily I needed encryption.
I found 3 easy to use but good encryption methods so if someone is looking for something like that, here it is in one place.
Here is the code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
public class NewBehaviourScript : MonoBehaviour {
//List to store variables
public static List<string> mylist = new List<string>();
//Key for XOR encryption
int key = 129;
//Just basic stopwatch so i can measure time
public Stopwatch time;
// Use this for initialization
void Start () {
time = new Stopwatch();
time.Start();
//Generates 10 blocks with x variable 0-10, y = 0-10, b = 0-3, saves them as string separated by , and then add string to list
for (int i = 0; i < 10; i++)
{
string a = "";
int x = Random.Range(0, 11);
int y = Random.Range(0, 11);
int b = Random.Range(0, 4);
a = x + "," + y + "," + b;
mylist.Add(a);
}
time.Stop();
print("Time to generate values" + time.Elapsed);
time.Reset();
//You can just ignore stopwatch functions
time.Start();
//Classic saving of strings
SaveInt();
time.Stop();
print("Int save time:" + time.Elapsed);
time.Reset();
time.Start();
//Saving by XOR encryption
SaveXOR();
time.Stop();
print("XOR save time:" + time.Elapsed);
time.Reset();
time.Start();
//Saving with binary formatter
SaveBinaryFormatter();
time.Stop();
print("BF save time:" + time.Elapsed);
time.Reset();
time.Start();
//Saving with binary formatter but with base 64
SaveBinaryFormatter64String();
time.Stop();
print("64 save time:" + time.Elapsed);
time.Reset();
}
//With StreamWriter saves all strings line by line to text file
void SaveInt()
{
StreamWriter file = new StreamWriter(Application.persistentDataPath + "/int.txt");
for (int i = 0; i < mylist.Count; i++)
{
string a = mylist[i];
file.WriteLine(a);
file.Flush();
}
file.Close();
}
//Takes string, encrypts string and then saves it to file
void SaveXOR()
{
StreamWriter file = new StreamWriter(Application.persistentDataPath + "/XOR.txt");
for (int i = 0; i < mylist.Count; i++)
{
string a = mylist[i];
file.WriteLine(EncryptDecrypt(a));
file.Flush();
}
file.Close();
}
//XOR encryption by key, basiclly it takes ASCII code of character and ^ by key, does that to each character of string
public string EncryptDecrypt(string textToEncrypt)
{
StringBuilder inSb = new StringBuilder(textToEncrypt);
StringBuilder outSb = new StringBuilder(textToEncrypt.Length);
char c;
for (int i = 0; i < textToEncrypt.Length; i++)
{
c = inSb[i];
c = (char)(c ^ key);
outSb.Append(c);
}
return outSb.ToString();
}
//Uses binary formatter to save data
void SaveBinaryFormatter()
{
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Create(Application.persistentDataPath + "/bf.txt");
bf.Serialize(file, mylist);
}
//Converts to string base 64 and then saves with binary formatter
void SaveBinaryFormatter64String()
{
BinaryFormatter bf = new BinaryFormatter();
StreamWriter file = new StreamWriter(Application.persistentDataPath + "/64.txt");
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, mylist);
string a = System.Convert.ToBase64String(ms.ToArray());
file.WriteLine(a);
file.Close();
}
First I saved normal string no encryption and line of data looks like this “7,3,0”
Second is XOR encryption which seems “unreadable” but is quite easy to brake and looks like this “¶´³”
Third is binary formatter which looks something like this " 7,5,2 "(it has some extra chars not recognized by forum)
Last and fourth is binary formatter but with base 64 and looks like this “AQAAAAAAAAAEAQAAAH9TeXN0ZW0uQ29sbGV”
(they are ordered by protection from weakest to strongest)
As you can see first one is really easy to break, just change some numbers and you are done, second and and third are a bit harder and last fourth seems strongest encryption.
Yeah but what is cost of processing power (I’m aiming for android phone so less processing power) and data size?
I made few tests to exactly show how each perform:
Here you can see how much time (in seconds) I needed to save file and how much space it takes with each encryption.
First basic string save is smallest but also 3rd in saving time, but is worst at data protection as it is easiest to edit by any user.
XOR encryption being 3rd by size (1st is smallest) and being slowest of them all sure is not good performance wise but it seems as “advanced encryption” and will drive off any hacker that is not determined to break the encryption (which I already said, is quite easy)
Binary formatting is very good as it is easy to setup in code, it is fastest (slowest at small amounts of variables but also it does not matter at such small time frame) and by size is 2nd after basic string saving method, also as I did’not find many info about security, it seems as it is better protected than XOR.
Base 64 even its saving size is biggest, it also is one of fastest right after BF and has one better protection than BF. But I find it has some trouble at loading because you also need to deserialize and convert back from base 64 as it returns object.
So, now you know more about saving game data to text files and can see visual code reference for easy setup and also see stats, how each method perform.
I also made graphs at bigger scale (5,000,000 needed for my project) to see how they compare at large data:
At higher scale XOR takes by far the longest time and BF needs almost half the time while comparing the size basic string is smallest and base 64 takes biggest space.
Conclusion:
If you store LARGE amount of data best method would be BF because of relative small size and is fastest while giving pretty decent protection but you would also need to compress the file (if some numbers are repeating they can be shrunk like xxxxx can be 5*x), as for smaller data types I would go for XOR because time is not of such essence and file size is not like SUPER BIG but seems very complicated to crack and is VERY easy to save/load.
Good luck at coding and I hope post is not boring or have too much useless stuff as I tried to combine everything at one place for future searches.