Memahami serialisasi

38

Saya seorang insinyur perangkat lunak dan setelah berdiskusi dengan beberapa rekan, saya menyadari bahwa saya tidak memiliki pemahaman yang baik tentang konsep serialisasi. Seperti yang saya mengerti, serialisasi adalah proses mengubah beberapa entitas, seperti objek dalam OOP, ke urutan byte, sehingga entitas tersebut dapat disimpan atau dikirim untuk akses selanjutnya (proses "deserialisasi").

Masalah yang saya miliki adalah: bukankah semua variabel (baik itu primitif intatau objek komposit) sudah diwakili oleh urutan byte? (Tentu saja, karena disimpan dalam register, memori, disk, dll.)

Jadi apa yang membuat serialisasi menjadi topik yang mendalam? Untuk membuat serial suatu variabel, tidak bisakah kita mengambil byte ini dalam memori, dan menulisnya ke file? Seluk beluk apa yang saya lewatkan?

ddcz
sumber
21
Serialisasi dapat menjadi hal sepele untuk objek yang berdekatan . Ketika nilai objek direpresentasikan sebagai grafik penunjuk , hal-hal menjadi jauh lebih rumit, terutama jika grafik tersebut memiliki loop.
chi
1
@chi: Kalimat pertama Anda sedikit menyesatkan mengingat kedekatan tidak relevan. Anda mungkin memiliki grafik yang terus menerus dalam memori dan itu masih tidak akan membantu Anda membuat cerita bersambung karena Anda masih harus (a) mendeteksi bahwa itu kebetulan bersebelahan, dan (b) memperbaiki pointer di dalam. Saya hanya akan mengatakan bagian kedua dari apa yang Anda katakan.
Mehrdad
@Mehrdad Saya setuju komentar saya tidak sepenuhnya tepat, untuk alasan yang Anda sebutkan. Mungkin pointer-free / pointer-using adalah perbedaan yang lebih baik (bahkan jika tidak sepenuhnya akurat, baik)
chi
7
Anda juga harus khawatir tentang representasi pada perangkat keras. Jika saya membuat serial int 4 bytespada PDP-11 saya dan kemudian mencoba dan membaca empat byte yang sama ke dalam memori di macbook saya mereka bukan nomor yang sama (karena Endianes). Jadi, Anda harus menormalkan data ke representasi yang dapat Anda hapus kode (ini adalah serialisasi). Bagaimana Anda membuat serialisasi data juga memiliki pengorbanan kecepatan / fleksibilitas yang dapat dibaca manusia / mesin.
Martin York
Bagaimana jika Anda menggunakan Entity Framework dengan banyak properti navigasi yang terhubung? Dalam satu kasus, Anda mungkin ingin membuat serialisasi properti navigasi, tetapi di lain membiarkannya nol (karena Anda akan memuat ulang objek yang sebenarnya dari database berdasarkan ID yang ada di objek induk serial Anda). Ini hanya satu contoh. Ada banyak.
ErikE

Jawaban:

40

Jika Anda memiliki struktur data yang rumit, perwakilannya dalam memori biasanya tersebar di seluruh memori. (Pikirkan pohon biner, misalnya.)

Sebaliknya, ketika Anda ingin menulisnya ke disk, Anda mungkin ingin memiliki representasi sebagai urutan (mudah-mudahan pendek) byte yang berdekatan. Itulah yang dilakukan serialisasi untuk Anda.

DW
sumber
27

Masalah yang saya miliki adalah: tidak semua variabel (baik itu primitif seperti objek int atau komposit) sudah diwakili oleh urutan byte? (Tentu saja, karena disimpan dalam register, memori, disk, dll.)

Jadi apa yang membuat serialisasi menjadi topik yang mendalam? Untuk membuat serial suatu variabel, tidak bisakah kita mengambil byte ini dalam memori, dan menulisnya ke file? Seluk beluk apa yang saya lewatkan?

Pertimbangkan grafik objek dalam C dengan node yang didefinisikan sebagai ini:

struct Node {
    struct Node* parent;
    struct Node* someChild;
    struct Node* anotherLink;

    int value;
    char* label;
};

//

struct Node nodes[10] = {0};
nodes[5].parent = nodes[0];
nodes[0].someChild = calloc( 1, sizeof(struct Node) );
nodes[5].anotherLink = nodes[3];
for( size_t i = 3; i < 7; i++ ) {
    nodes[i].anotherLink = calloc( 1, sizeof(struct Node) );
}

Pada saat runtime, seluruh Nodegrafik objek akan tersebar di sekitar ruang memori, dan simpul yang sama dapat diarahkan ke banyak Node yang berbeda.

Anda tidak bisa begitu saja membuang memori ke file / stream / disk dan menyebutnya serialized karena nilai pointer (yang merupakan alamat memori) tidak dapat di-serialkan (karena lokasi memori tersebut mungkin sudah ditempati ketika Anda memuat dump kembali ke dalam memori). Masalah lain dengan hanya membuang memori adalah bahwa Anda pada akhirnya akan menyimpan semua jenis data yang tidak relevan dan ruang yang tidak digunakan - pada x86 sebuah proses memiliki ruang memori hingga 4Gb, dan OS atau MMU hanya memiliki gambaran umum tentang apa sebenarnya memori bermakna atau tidak (berdasarkan halaman memori yang ditugaskan untuk suatu proses), jadi memiliki Notepad.exedump 4GB byte mentah ke disk saya setiap kali saya ingin menyimpan file teks sepertinya agak boros.

Masalah lain adalah dengan versi: apa yang terjadi jika Anda membuat serial Nodegrafik Anda pada hari 1, kemudian pada hari 2 Anda menambahkan bidang lain ke Node(seperti nilai pointer lain, atau nilai primitif), maka pada hari ke 3 Anda membatalkan serialisasi file Anda dari hari 1?

Anda juga harus mempertimbangkan hal-hal lain, seperti endianness. Salah satu alasan utama mengapa file MacOS dan IBM / Windows / PC tidak kompatibel satu sama lain pada 1980-an dan 1990-an meskipun seolah-olah sedang dibuat oleh program yang sama (Word, Photoshop, dll) adalah karena nilai integer x86 / PC multi-byte multi-byte disimpan dalam urutan little-endian, tetapi pesanan big-endian pada Mac - dan perangkat lunak tidak dibuat dengan mempertimbangkan portabilitas lintas-platform. Saat ini segalanya menjadi lebih baik berkat peningkatan pendidikan pengembang dan dunia komputasi kami yang semakin heterogen.

Dai
sumber
2
Membuang semua yang ada di ruang memori proses juga akan mengerikan karena alasan keamanan. Malam acara ada di memori, 1) beberapa data publik, dan 2) kata sandi, kunci rahasia, atau kunci pribadi. Ketika membuat serial yang pertama, seseorang tidak ingin mengungkapkan informasi apa pun tentang yang terakhir.
chi
8
Catatan yang sangat menarik tentang topik ini: Mengapa format file Microsoft Office sangat rumit?
mencolok
15

Caranya sebenarnya sudah dijelaskan dalam kata itu sendiri: " serial ization".

Pertanyaannya pada dasarnya adalah: bagaimana saya bisa mewakili grafik yang diarahkan kompleks kompleks yang saling terhubung secara arbitrer dari objek kompleks semena-mena sebagai urutan linear byte?

Pikirkan tentang hal ini: urutan linier adalah seperti grafik terarah degenerasi di mana setiap titik memiliki tepat satu tepi masuk dan keluar (kecuali "simpul pertama" yang tidak memiliki tepi masuk dan "simpul terakhir" yang tidak memiliki tepi keluar) . Dan byte jelas kurang kompleks daripada objek .

Jadi, tampaknya masuk akal bahwa ketika kita beralih dari grafik yang kompleks sewenang-wenang ke "grafik" yang jauh lebih terbatas (sebenarnya hanya sebuah daftar) dan dari objek yang kompleks semena-mena ke byte sederhana, informasi akan hilang, jika kita melakukan ini secara naif dan tidak t menyandikan informasi "asing" dengan cara tertentu. Dan itulah yang dilakukan serialisasi: menyandikan informasi kompleks ke dalam format linear sederhana.

Jika Anda terbiasa dengan YAML , Anda mungkin harus melihat fitur anchor dan alias yang memungkinkan Anda untuk mewakili gagasan bahwa "objek yang sama dapat muncul di tempat yang berbeda" dalam serialisasi.

Misalnya jika Anda memiliki grafik berikut:

A → B → D
↓       ↑
C ––––––+

Anda dapat menyatakan bahwa sebagai daftar jalur linear di YAML seperti ini:

- [&A A, B, &D D]
- [*A, C, *D]

Anda juga bisa mewakilinya sebagai daftar adjacency, atau matriks adjacency, atau sebagai pasangan yang elemen pertamanya adalah serangkaian node dan yang elemen keduanya adalah kumpulan pasangan node, tetapi dalam semua representasi itu, Anda harus memiliki cara merujuk mundur dan maju ke node yang ada , yaitu pointer , yang biasanya tidak Anda miliki dalam file atau aliran jaringan. Yang Anda miliki, pada akhirnya, adalah byte.

(Yang BTW berarti bahwa file teks YAML di atas itu sendiri juga perlu "serial", itulah yang digunakan untuk berbagai pengkodean karakter dan format transfer Unicode ... itu bukan "serialisasi" semata, hanya pengkodean, karena file teks sudah menjadi serial / Daftar linear dari codepoint, tetapi Anda dapat melihat beberapa kesamaan.)

Jörg W Mittag
sumber
13

Jawaban lain sudah membahas grafik objek yang kompleks, tetapi ada baiknya menunjukkan bahwa serialisasi primitif juga non-sepele.

Menggunakan nama tipe C primitif untuk konkret, pertimbangkan:

  1. Saya membuat serial a long. Beberapa waktu kemudian saya de-cerita bersambung, tapi ... pada platform yang berbeda, dan sekarang longadalah int64_tdaripada int32_tsaya disimpan. Jadi, saya harus sangat berhati-hati tentang ukuran yang tepat dari setiap jenis yang saya simpan, atau menyimpan beberapa metadata yang menjelaskan jenis dan ukuran setiap bidang.

    Perhatikan bahwa platform yang berbeda ini bisa saja platform yang sama setelah kompilasi ulang di masa depan.

  2. Saya membuat serial sebuah int32_t. Beberapa waktu kemudian saya membatalkan serialisasi, tapi ... pada platform yang berbeda, dan sekarang nilainya rusak. Sayangnya saya menyimpan nilai pada platform big-endian, dan memuatnya pada little-endian. Sekarang saya perlu membuat konvensi untuk format saya, atau menambahkan lebih banyak metadata yang menggambarkan endiannness dari setiap file / stream / apa pun. Dan, tentu saja, benar-benar melakukan konversi yang sesuai.

  3. Saya membuat serial sebuah string. Kali ini satu platform menggunakan chardan UTF-8, dan satu wchar_tdan UTF-16.

Jadi, saya akan mengklaim bahwa serialisasi berkualitas wajar tidak sepele bahkan untuk primitif dalam memori yang berdekatan. Ada banyak keputusan penyandian yang perlu Anda dokumentasikan, atau uraikan dengan metadata sebaris.

Grafik objek menambahkan lapisan kompleksitas lainnya di atas itu.

Tak berguna
sumber
6

Ada beberapa aspek:

Keterbacaan oleh program yang sama

Program Anda entah bagaimana menyimpan data Anda sebagai byte dalam memori. Tapi itu mungkin secara sewenang-wenang tersebar di register yang berbeda, dengan pointer bolak-balik di antara bagian-bagian yang lebih kecil [sunting: Seperti dikomentari, secara fisik data lebih mungkin di memori utama daripada register data, tetapi itu tidak menghilangkan masalah pointer] . Pikirkan saja daftar bilangan bulat yang ditautkan. Setiap elemen daftar dapat disimpan di tempat yang sama sekali berbeda dan semua yang menyatukan daftar adalah petunjuk dari satu elemen ke elemen berikutnya. Jika Anda mengambil data apa adanya dan mencoba menyalinnya di komputer lain yang menjalankan program yang sama, Anda akan mengalami masalah:

  1. Pertama dan yang terpenting, register memberi tahu data Anda disimpan di dalam satu mesin yang mungkin sudah digunakan untuk sesuatu yang sama sekali berbeda di komputer lain (seseorang sedang menelusuri pertukaran tumpukan dan browser sudah memakan semua memori itu). Jadi, jika Anda hanya menimpa register tersebut, selamat tinggal browser. Dengan demikian, Anda perlu mengatur ulang pointer dalam struktur agar sesuai dengan alamat yang Anda miliki di mesin kedua. Masalah yang sama muncul ketika Anda mencoba memuat ulang data pada mesin yang sama di lain waktu.
  2. Bagaimana jika beberapa komponen eksternal menunjuk ke struktur Anda atau struktur Anda memiliki pointer ke data eksternal, Anda tidak mengirim? Segfault di mana-mana! Ini akan menjadi mimpi buruk debugging.

Keterbacaan oleh program lain

Katakanlah Anda berhasil mengalokasikan alamat yang tepat di komputer lain, agar data Anda cocok. Jika data Anda diproses oleh program terpisah pada mesin itu (bahasa yang berbeda), program itu mungkin memiliki pemahaman dasar data yang sama sekali berbeda. Katakanlah Anda memiliki objek C ++ dengan pointer, tetapi bahasa target Anda bahkan tidak mendukung pointer pada level itu. Sekali lagi, Anda berakhir dengan tidak ada cara yang bersih untuk menangani data itu dalam program kedua. Anda berakhir dengan beberapa data biner dalam memori, tetapi kemudian, Anda perlu menulis kode tambahan yang membungkus data dan entah bagaimana menerjemahkannya menjadi sesuatu yang dapat digunakan oleh bahasa target Anda. Kedengarannya seperti deserialization, hanya saja titik awal Anda sekarang adalah benda aneh yang tersebar di sekitar memori utama Anda, yang berbeda untuk bahasa sumber yang berbeda, bukannya file dengan struktur yang terdefinisi dengan baik. Hal yang sama, tentu saja, jika Anda mencoba untuk secara langsung menginterpretasikan file biner yang mencakup pointer - Anda perlu menulis parser untuk setiap cara yang mungkin bahasa lain mewakili data dalam memori.

Keterbacaan oleh manusia

Dua bahasa serialisasi modern yang paling menonjol untuk serialisasi berbasis web (xml, json) mudah dimengerti oleh manusia. Alih-alih tumpukan biner dari goo, struktur aktual dan konten data jelas bahkan tanpa program untuk membaca data. Ini memiliki beberapa keunggulan:

  • lebih mudah debugging -> jika ada masalah dalam saluran layanan Anda, Anda cukup melihat data yang keluar dari satu layanan dan memeriksa apakah itu masuk akal (sebagai langkah pertama); Anda juga secara langsung melihat apakah data tampak seperti yang Anda pikir seharusnya, ketika Anda menulis antarmuka ekspor Anda di tempat pertama.
  • kearsipan: jika Anda memiliki data sebagai tumpukan biner murni, dan Anda kehilangan program yang dimaksudkan untuk menafsirkannya, Anda kehilangan data (atau Anda harus menghabiskan beberapa waktu untuk benar-benar menemukan sesuatu di sana); jika data serial Anda siap digunakan manusia, Anda dapat dengan mudah menggunakannya sebagai arsip atau memprogram importir Anda sendiri untuk program baru
  • sifat deklaratif data yang diserialkan sedemikian rupa, juga berarti, ia sepenuhnya independen dari sistem komputer dan perangkat kerasnya; Anda dapat memuatnya ke dalam komputer kuantum yang dibangun secara berbeda sama sekali atau menginfeksi AI alien dengan fakta-fakta alternatif sehingga secara tidak sengaja terbang ke matahari berikutnya (Emmerich jika Anda membaca ini, referensi akan lebih baik, jika Anda menggunakan ide itu untuk 4 Juli mendatang film)
Frank Hopkins
sumber
Data saya mungkin sebagian besar di memori utama, bukan di register. Jika data saya cocok dengan register, serialisasi hampir tidak menjadi masalah. Saya pikir Anda telah salah memahami apa itu register.
David Richerby
Memang, saya menggunakan istilah register terlalu longgar di sini. Tetapi poin utama adalah bahwa data Anda dapat berisi pointer ke ruang alamat untuk mengidentifikasi komponennya sendiri atau untuk merujuk ke data lain. Tidak masalah apakah itu register fisik atau alamat virtual di memori utama.
Frank Hopkins
Tidak, Anda menggunakan istilah "daftar" sepenuhnya salah. Hal-hal yang Anda panggil register berada di bagian hierarki memori yang sama sekali berbeda dengan register yang sebenarnya.
David Richerby
6

Selain apa yang dikatakan jawaban lain:

Terkadang Anda ingin membuat serial hal-hal yang bukan data murni.

Sebagai contoh, pikirkan file handle atau koneksi ke server. Meskipun pegangan file atau soketnya adalah int, angka ini tidak berarti apa-apa saat berikutnya program dijalankan. Untuk membuat ulang objek dengan benar yang berisi pegangan untuk hal-hal seperti itu, Anda perlu membuka kembali file dan membuat ulang koneksi, dan memutuskan apa yang harus dilakukan jika ini gagal.

Banyak bahasa saat ini mendukung penyimpanan fungsi anonim dalam objek, misalnya onBlah()penangan dalam Javascript. Ini menantang karena kode tersebut dapat berisi referensi ke potongan data tambahan yang pada gilirannya perlu diserialisasi. (Dan kemudian ada masalah kode serialisasi dalam cara lintas-platform, yang jelas lebih mudah untuk bahasa yang ditafsirkan.) Namun, bahkan jika hanya sebagian dari bahasa yang dapat didukung, masih dapat terbukti sangat berguna. Tidak banyak mekanisme serialisasi yang mencoba kode serialisasi, tetapi lihat serialize-javascript .

Dalam kasus di mana Anda ingin membuat serial objek, tetapi berisi sesuatu yang tidak didukung oleh mekanisme serialisasi Anda, Anda perlu menulis ulang kode dengan cara yang bekerja di sekitar ini. Misalnya, Anda dapat menggunakan enum sebagai pengganti fungsi anonim saat ada sejumlah fungsi yang mungkin.

Seringkali Anda ingin data berseri menjadi singkat.

Jika Anda mengirim data melalui jaringan atau bahkan menyimpannya di disk, penting untuk menjaga ukurannya tetap kecil. Salah satu cara termudah untuk mencapai ini adalah membuang informasi yang dapat dibangun kembali (misalnya, membuang cache, tabel hash, dan representasi alternatif dari data yang sama).

Tentu saja, programmer harus memilih secara manual apa yang akan disimpan dan apa yang harus dibuang, dan memastikan semuanya dibangun kembali ketika objek diciptakan kembali.

Pikirkan tentang tindakan menyelamatkan permainan. Objek mungkin mengandung banyak pointer ke data grafik, data suara, dan objek lainnya. Tetapi sebagian besar hal ini dapat dimuat dari file data game dan tidak perlu disimpan dalam file save. Membuangnya bisa melelahkan sehingga hal-hal kecil sering ditinggalkan. Saya telah mengedit beberapa file yang disimpan di waktu saya dan menemukan data yang jelas-jelas berlebihan, seperti deskripsi item tekstual.

Kadang-kadang ruang tidak penting tetapi keterbacaan adalah — dalam hal ini Anda mungkin menggunakan format ASCII (mungkin JSON atau XML).

Artelius
sumber
3

Mari kita tentukan apa sebenarnya urutan byte itu. Urutan byte terdiri dari bilangan bulat non-negatif yang disebut panjang dan beberapa fungsi / korespondensi arbitrer yang memetakan sembarang bilangan bulat i yang setidaknya nol dan kurang dari panjang ke nilai byte (bilangan bulat dari 0 hingga 255).

Banyak objek yang Anda tangani dalam program tipikal tidak dalam bentuk itu, karena objek sebenarnya terdiri dari banyak alokasi memori berbeda yang berada di tempat yang berbeda dalam RAM, dan dapat dipisahkan dari satu sama lain oleh jutaan byte barang yang Anda miliki. tidak peduli. Bayangkan saja daftar tertaut dasar: setiap node dalam daftar adalah urutan byte, ya, tetapi node berada di banyak lokasi berbeda di memori komputer Anda, dan mereka terhubung dengan pointer. Atau pikirkan saja struct sederhana yang memiliki pointer ke string panjang variabel.

Alasan mengapa kami ingin membuat serial struktur data menjadi urutan byte biasanya karena kami ingin menyimpannya di disk atau mengirimnya ke sistem yang berbeda (misalnya melalui jaringan). Jika Anda mencoba untuk menyimpan pointer pada disk atau mengirimnya ke sistem yang berbeda, itu akan sangat tidak berguna karena program yang membaca pointer itu akan memiliki set area memori yang berbeda tersedia.

David Grayson
sumber
1
Saya tidak yakin itu definisi yang bagus dari suatu urutan. Kebanyakan orang akan mendefinisikan urutan menjadi, well, urutan: serangkaian hal satu demi satu. Menurut definisi Anda, int seq(int i) { if (0 <= i < length) return i+1; else return -1;}adalah urutan. Jadi bagaimana saya akan menyimpannya di disk?
David Richerby
1
Jika panjangnya 4, saya menyimpan file empat byte dengan konten: 1, 2, 3, 4.
David Grayson
1
@DavidRicherbyDefinisinya setara dengan "sederetan hal satu demi satu", itu hanya definisi yang lebih matematis dan tepat daripada definisi intuitif Anda. Perhatikan bahwa fungsi Anda bukan urutan karena untuk memiliki urutan Anda perlu fungsi itu dan bilangan bulat lain yang disebut panjang.
user253751
1
@FreshAir Maksud saya adalah urutannya adalah 1, 2, 3, 4, 5. Hal yang saya tulis adalah fungsi . Fungsi bukan urutan.
David Richerby
1
Cara sederhana untuk menulis fungsi ke disk adalah yang sudah saya usulkan: untuk setiap input yang mungkin, simpan hasilnya. Saya pikir mungkin Anda masih belum mengerti, tetapi saya tidak yakin harus mengatakan apa. Tahukah Anda bahwa dalam embedded system, biasanya mengubah fungsi yang mahal seperti sinmenjadi tabel pencarian, yang merupakan urutan angka? Tahukah Anda fungsi Anda sama dengan yang ini untuk input yang kami pedulikan? int seq(n) { int a[] = [1, 2, 3, 4]; return a[n]; } Mengapa tepatnya Anda mengatakan bahwa file empat byte saya adalah representasi yang tidak memadai?
David Grayson
2

Seluk-beluk mencerminkan seluk-beluk data dan objek itu sendiri. Objek-objek ini dapat berupa objek dunia nyata, atau hanya objek komputer. Jawabannya ada dalam nama. Serialisasi adalah representasi linear dari objek multi dimensional. Ada banyak masalah selain RAM yang terfragmentasi.

Jika Anda dapat meratakan 12 array lima dimensi dan beberapa kode program, serialisasi juga memungkinkan Anda untuk mentransfer seluruh program komputer (dan data) antar mesin. Protokol komputasi terdistribusi seperti RMI / CORBA menggunakan serialisasi secara ekstensif untuk mentransfer data dan program.

Pertimbangkan tagihan telepon Anda. Mungkin objek tunggal, terdiri dari semua panggilan Anda (daftar string), jumlah yang harus dibayar (integer) dan negara. Atau tagihan telepon Anda bisa dari luar ke atas dan terdiri dari panggilan telepon terperinci diskrit yang ditautkan dengan nama Anda. Setiap bagian yang rata akan terlihat berbeda, mencerminkan bagaimana perusahaan telepon Anda menulis bahwa versi perangkat lunaknya dan alasan mengapa basis data berorientasi objek tidak pernah lepas landas.

Beberapa bagian struktur bahkan mungkin tidak ada dalam memori sama sekali. Jika Anda memiliki caching yang malas, beberapa bagian dari objek mungkin hanya dirujuk ke file disk, dan hanya dimuat ketika bagian dari objek tertentu diakses. Ini biasa terjadi dalam kerangka kegigihan yang serius. Gumpalan adalah contoh yang bagus. Getty Images dapat menyimpan gambar multimabyte besar Fidel Castro dan beberapa data meta seperti nama gambar, biaya sewa dan gambar itu sendiri. Anda mungkin tidak ingin memuat gambar 200 MB ke dalam memori setiap kali, kecuali jika Anda benar-benar melihatnya. Serialized, seluruh file akan membutuhkan lebih dari 200MB penyimpanan.

Beberapa objek bahkan tidak dapat diserialisasi sama sekali. Di tanah pemrograman Java, Anda dapat memiliki objek pemrograman yang mewakili layar grafis atau port serial fisik. Tidak ada konsep serialisasi yang nyata dari keduanya. Bagaimana Anda mengirim port Anda ke orang lain melalui jaringan?

Beberapa hal seperti kata sandi / kunci enkripsi tidak boleh disimpan atau dikirim. Mereka dapat ditandai seperti itu (volatile / transient dll) dan proses serialisasi akan melompati mereka tetapi mereka dapat hidup dalam RAM. Menghilangkan tag ini adalah bagaimana kunci enkripsi secara tidak sengaja dikirim / disimpan dalam ASCII biasa.

Ini dan jawaban lainnya adalah mengapa ini rumit.

Paul Uszak
sumber
2

Masalah yang saya miliki adalah: tidak semua variabel (baik itu primitif seperti objek int atau komposit) sudah diwakili oleh urutan byte?

Iya itu mereka. Masalahnya di sini adalah tata letak byte tersebut. Sederhana intbisa 2, 4 atau 8 bit. Bisa dalam endian besar atau kecil. Itu dapat ditandatangani, ditandatangani dengan komplemen 1 atau bahkan dalam beberapa kode bit super eksotis seperti negabinary.

Jika Anda hanya membuang intbinarily dari memori, dan menyebutnya "serial", Anda harus memasang cukup banyak seluruh komputer, sistem operasi dan program Anda agar dapat deserializable. Atau setidaknya, deskripsi yang tepat tentang mereka.

Jadi apa yang membuat serialisasi menjadi topik yang mendalam? Untuk membuat serial suatu variabel, tidak bisakah kita mengambil byte ini dalam memori, dan menulisnya ke file? Seluk beluk apa yang saya lewatkan?

Serialisasi objek sederhana cukup banyak menuliskannya menurut beberapa aturan. Aturan-aturan itu banyak dan tidak selalu jelas. Misalnya xs:integerdalam XML ditulis dalam basis-10. Bukan base-16, bukan base-9, tapi 10. Ini bukan asumsi tersembunyi, itu aturan yang sebenarnya. Dan aturan seperti itu membuat serialisasi menjadi serialisasi. Karena, cukup banyak, tidak ada aturan tentang tata letak bit program Anda di memori .

Itu hanya puncak gunung es. Mari kita mengambil contoh dari urutan orang-orang primitif yang paling sederhana: C struct. Anda bisa memikirkan itu

struct {
short width;
short height;
long count;
}

memiliki tata letak memori yang ditentukan pada komputer + OS yang diberikan? Ya tidak. Bergantung pada #pragma packpengaturan saat ini , kompiler akan mengisi bidang. Pada pengaturan default kompilasi 32-bit, keduanya shortsakan diisi hingga 4 byte sehingga structsebenarnya akan memiliki 3 bidang 4 byte dalam memori. Jadi sekarang, Anda tidak hanya harus menentukan bahwa short16 bit panjang, itu adalah bilangan bulat, ditulis dalam komplemen negatif 1, endian besar atau kecil. Anda juga harus menuliskan pengaturan struktur packing program Anda dikompilasi.

Itulah yang dimaksud dengan serialisasi: membuat seperangkat aturan, dan berpegang teguh padanya.

Aturan-aturan itu kemudian dapat diperluas untuk menerima struktur yang lebih canggih (seperti daftar panjang variabel atau data nonlinear), fitur tambahan seperti keterbacaan manusia, versi, kompatibilitas mundur dan koreksi kesalahan, dll. Tetapi bahkan menulis satu pun intsudah cukup rumit jika Anda hanya ingin memastikan Anda dapat membacanya kembali dengan andal.

Agent_L
sumber