Я кодирую игру на основе Java-плитки, и мне интересен лучший способ сохранить действительно большую карту плитки в базе данных. (Вся карта разделена на куски.)
Я могу хранить данные плитки как 2D-массив или массив строк (для каждого фрагмента), например:
["1100111223333",
"3130111213333",
"1300311233333",
.............................]
где каждый номер представляет собой бетонную черепицу.
Этот подход является самым легким, но когда я использую действительно большую карту, такую как 20000x20000 плитки, она занимает неприличную массу памяти!
По моим подсчетам: если массив 20000x20000, и каждая плитка использует 3 байта (я точно не знаю, сколько пространства занимает символ в строке), то 20000 * 20000 * 3 = 1200000000 байт или 1,14 ГБ !
Думаю, это слишком много места.
Возможно, я также могу хранить данные в форме:
["G18W3S23G12W3",
["W13G3S5G12W3",
.................................]
что означает 18 плиток травы, затем 3 плитки воды, затем 2 плитки из песка и так далее...
Но я думаю, что это плохой подход.
Вероятно, я могу создавать изображения для каждого фрагмента и получать из него фрагменты, но довольно сложно использовать изображения в базе данных, не так ли?
Так как я могу сделать это наиболее эффективно?
PS: Я использую массив строк, потому что я понятия не имею, как создать 2d-массив в SQL (возможно ли это?)
Поскольку это процедурно сгенерировано, у вас есть очень хороший способ оптимизировать ваши файлы сохранения. Вы можете сделать версию minecraft: сохранить свое семя, чтобы вам не нужно было сохранять всю карту, а затем сохранить плитки, которые были изменены после генерации каждого фрагмента карты.
Затем, когда вы загружаете, генерируете необходимые куски на основе вашего семени и применяете модификации.
может показаться простым, но вы можете использовать сжатие! (и уже может быть слишком поздно, хахааа)
если вы знаете, как работает сжатие Хаффмана (http://en.wikipedia.org/wiki/Huffman_coding), вы обнаружите, что ваше хранилище может сильно сократиться...
и как только вы знаете, что Java МОЖЕТ УЖЕ сделать это за вас, вот мой простой подход...
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class Abc {
public static void main(String[] args) {
new Abc().doIt();
}
private void doIt() {
try {
//create a big Object (well my string might not be big)
String veryBigObject = new String("have a class that implements serializable, like String") ;
File file = new File("myFile.bin");
//write it as zipped stream into a file
ObjectOutputStream oos = new ObjectOutputStream(new GZIPOutputStream(new FileOutputStream(file) ) );
oos.writeObject(veryBigObject);
oos.close();
//read it back again
ObjectInputStream ois = new ObjectInputStream(new GZIPInputStream(new FileInputStream(file) ) );
String loadedInstance = (String)ois.readObject();
ois.close();
System.out.println(loadedInstance);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
то это результат:
have a class that implements serializable, like String
я надеюсь, что я не слишком поздно
Почему вы хотите загрузить все сразу? Вы разделили его на куски, чтобы не загружать все, не так ли?
Идея, которую у вас есть, уже хороша. Сжатие значительно уменьшит размер (даже просто кодировку длины, как и ваш пример, но другие алгоритмы, такие как zip). Если вы уже разделили данные на куски, тогда просто сжимайте каждый отдельно и разгружайте его "на лету", когда вы загружаете (и вы не будете загружать сразу все данные). Меняются ли куски? Если нет, вы можете просто работать с простым почтовым файлом вместо базы данных. Если они меняются, тогда не делайте этого, zip файлы не могут быть легко изменены.