Kaip sukurti savo serializacijos protokolą?
sobes.tech AI
Atsakymas iš AI
Norint sukurti savo serializacijos protokolą Java, reikia nustatyti duomenų formatą ir įgyvendinti skaitymo/rašymo logiką.
-
Nustatyti duomenų formatą: Spręsti, kaip objektai bus pateikiami baitų formatu. Tai gali būti binarinis formatas (kompaktiškesnis) arba tekstinis (labiau skaitomas). Pavyzdžiui, galima naudoti ilgio prefiksą prieš laukus.
-
Įgyvendinti skaitymą ir rašymą:
- Sukurti klasę
MySerializer(ar panašią), kuri turės metodusserializeirdeserialize. - Metodas
serializepriims objektą irOutputStream, įrašydamas objekto baitus į srautą pagal nustatytą formatą. - Metodas
deserializepriimsInputStreamir atkurs objektą iš baitų.
- Sukurti klasę
-
Žymėti klases serializacijai: Klasės, kurias reikia serializuoti, turi turėti mechanizmą sąveikai su serializatoriumi. Tai gali būti:
Serializablesąsajos įgyvendinimas (bet tada bus naudojamas standartinis Java mechanizmas).- Naudotojo apibrėžti metodai
writeObjectirreadObject(panašiai kaipreadObjectirwriteObjectstandartinei serializacijai, bet su savo parašais). - Anotacijų naudojimas nurodyti laukus, kurie turi būti serializuoti, ir jų tvarką.
-
Nuorodų apdorojimas: Apsvarstyti, kaip serializuoti objektus su ciklinėmis nuorodomis ar dubliuojančiomis nuorodomis į tą patį objektą. Galima naudoti ID mechanizmą.
-
Versijų apdorojimas: Numatyti, kaip bus vykdoma deserializacija iš senesnės protokolo versijos duomenų.
Pavyzdinis bazinis įgyvendinimas (be sudėtingų atvejų apdorojimo):
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class MySerializer {
// Rašo sveikojo skaičiaus lauką
public void writeInt(OutputStream os, int value) throws IOException {
os.write((value >>> 24) & 0xFF);
os.write((value >>> 16) & 0xFF);
os.write((value >>> 8) & 0xFF);
os.write((value >>> 0) & 0xFF);
}
// Skaito sveikojo skaičiaus lauką
public int readInt(InputStream is) throws IOException {
int value = 0;
value = (is.read() << 24);
value |= (is.read() << 16);
value |= (is.read() << 8);
value |= (is.read() << 0);
return value;
}
// Rašo eilutės lauką (paprastas būdas: ilgis + eilutės baitai)
public void writeString(OutputStream os, String value) throws IOException {
byte[] bytes = value.getBytes("UTF-8");
writeInt(os, bytes.length); // Rašo eilutės ilgį
os.write(bytes); // Rašo eilutės baitus
}
// Skaito eilutės lauką
public String readString(InputStream is) throws IOException {
int length = readInt(is); // Skaito eilutės ilgį
byte[] bytes = new byte[length];
is.read(bytes); // Skaito eilutės baitus
return new String(bytes, "UTF-8");
}
// Pavyzdys serializuojant paprastą Person objektą
public void serialize(OutputStream os, Person person) throws IOException {
writeString(os, person.getName());
writeInt(os, person.getAge());
}
// Pavyzdys deserializuojant Person objektą
public Person deserialize(InputStream is) throws IOException {
String name = readString(is);
int age = readInt(is);
return new Person(name, age);
}
// Pagalbinė klasė pavyzdžiui
public static class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
public static void main(String[] args) throws IOException {
MySerializer serializer = new MySerializer();
Person originalPerson = new Person("Alice", 30);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
serializer.serialize(baos, originalPerson);
byte[] serializedData = baos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(serializedData);
Person deserializedPerson = serializer.deserialize(bais);
System.out.println("Originalas: " + originalPerson.getName() + ", " + originalPerson.getAge());
System.out.println("Deserializuotas: " + deserializedPerson.getName() + ", " + deserializedPerson.getAge());
}
}
Sukurti savo protokolą reikalauja kruopštaus planavimo ir daugelio veiksnių apsvarstymo, tokių kaip našumas, kompaktiškumas, versijavimas ir sudėtingų duomenų struktūrų apdorojimas. Dažnai naudojamos jau esamos bibliotekos (ProtoBuf, Kryo, Avro) vietoje nuo nulio kuriant protokolą.