Serileştirmeyi anlama


38

Ben bir yazılım mühendisiyim ve bazı meslektaşlarımla yaptığım görüşmeden sonra, kavram serileştirme kavramını iyi anlamadığımı fark ettim. Anladığım kadarıyla seri hale getirme, OOP'deki bir nesne gibi bazı varlıkları bir bayt sırasına dönüştürme işlemidir, böylece adı geçen varlık daha sonra erişim için ("seri hale getirme işlemi") saklanabilir veya iletilebilir.

Karşılaştığım sorun şu: intzaten bir bayt dizisi tarafından temsil edilen tüm değişkenler (ilkel gibi veya bileşik nesneler gibi ) değil mi? (Tabii ki onlar, çünkü sicillerde, bellekte, diskte vb. Depolanırlar)

Peki seri hale getirmeyi böylesine derin bir konu yapan nedir? Bir değişkeni serileştirmek için, bu baytları bellekte alıp bir dosyaya yazamaz mıyız? Hangi inceliklerini kaçırdım?


21
Seri hale getirme bitişik nesneler için önemsiz olabilir . Nesne değeri bir işaretçi grafiği olarak gösterildiğinde , özellikle söz konusu grafikte halkalar varsa işler çok daha zorlaşır.
Chi

1
@chi: İlk cümleniz, bitişikliğin önemsiz olması nedeniyle biraz yanıltıcıdır. Bellekte sürekli olan ve hala seri hale getirme konusunda size yardımcı olmayacak bir grafiğe sahip olabilirsiniz (a) gerçekten de bitişik olduğunu algılamanız ve (b) içindeki imleçleri sabitlemeniz gerekir. Sadece söylediklerinin ikinci kısmını söyleyebilirim.
Mehrdad

@Mehrdad Bahsettiğim nedenlerden dolayı yorumumun tam olarak doğru olmadığını kabul ediyorum. İşaretçi-ücretsiz / işaretçi-kullanma belki daha iyi bir ayrımdır (tamamen doğru olmasa bile)
chi

7
Ayrıca donanımın temsili konusunda endişelenmeniz gerekir. 4 bytesPDP- 11'imde bir int seri hale getirirseniz ve aynı dört byte'ı macbook'umdaki belleğe okumaya çalışırsam aynı numara değildir (Endian'lar yüzünden). Bu nedenle, verileri deşifre edebileceğiniz bir gösterime göre normalleştirmeniz gerekir (bu seri hale getirmedir). Verileri nasıl seri hale getirdiğinize göre, insan / makine tarafından okunabilen hız / esneklik de vardır.
Martin York

Entity Framework'ü derinlemesine bağlı birçok navigasyon özelliği ile kullanıyorsanız ne olur? Bir durumda, bir gezinti özelliğini serileştirmek isteyebilirsiniz, ancak başka bir durumda onu boş bırakın (çünkü bu gerçek nesneyi serileştirilmiş üst nesnenizdeki kimliği temel alarak veritabanından yeniden yükleyeceksiniz). Bu sadece bir örnek. Çok var.
ErikE

Yanıtlar:


40

Karmaşık bir veri yapınız varsa, bellekteki temsili normalde bellek boyunca dağılmış olabilir. (Örneğin bir ikili ağacı düşünün.)

Buna karşılık, diske yazmak istediğinizde, muhtemelen (bayt olarak kısa) bitişik bayt dizisi olarak bir gösterime sahip olmak istersiniz. Serileştirme sizin için bunu yapar.


27

Karşılaştığım sorun şu: zaten bir bayt dizisi tarafından temsil edilen tüm değişkenler (int veya kompozit nesneler gibi ilkel olabilir) değil mi? (Tabii ki onlar, çünkü sicil, hafıza, disk vb.

Peki seri hale getirmeyi böylesine derin bir konu yapan nedir? Bir değişkeni serileştirmek için, bu baytları bellekte alıp bir dosyaya yazamaz mıyız? Hangi inceliklerini kaçırdım?

Bu şekilde tanımlanan düğümlerle C'deki bir nesne grafiğini düşünün:

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) );
}

Çalışma zamanında, tüm nesne Nodegrafiği bellek alanı etrafına dağılmış olacak ve aynı düğüm birçok farklı Düğümden işaretlenebilecektir.

Belleği bir dosyaya / akışa / diske atamaz ve seri hale getiremezsiniz, çünkü işaretçi değerleri (bellek adresleridir) seri hale getirilemez (çünkü bu bellek konumlarını, dökümü geri yüklediğinizde zaten dolu olabilir) hafızaya). Basitçe bellek dökümü ile ilgili diğer bir problem, her türlü alakasız veriyi ve kullanılmayan alanı saklamaya başlayacağınızdır - x86'da bir işlem 4GiB'ye kadar bellek alanına sahiptir ve bir işletim sistemi ya da MMU, yalnızca belleğin gerçekte ne olduğu hakkında genel bir fikre sahiptir. anlamlı olsun ya da olmasın (bir işleme atanan bellek sayfalarına göre), bu yüzden Notepad.exebir metin dosyasını kaydetmek istediğimde diskime 4GB'lık raw bayt atmak biraz zararlı görünüyor.

Başka bir sorun ise sürümle ilgilidir: Nodegrafiğinizi 1. günde seri hale getirirseniz , sonra 2. günde başka bir alan eklerseniz Node(başka bir işaretçi değeri veya ilkel bir değer gibi), ardından 3. günde dosyanızı seri hale getirirsiniz. 1.gün?

Aynı zamanda endianness gibi başka şeyleri de düşünmelisin. MacOS ve IBM / Windows / PC dosyalarının aynı programlar (Word, Photoshop, vb.) Tarafından görünüşte olmasına rağmen 1980'lerde ve 1990'larda birbirleriyle uyumsuz olmasının ana nedenlerinden biri de x86 / PC çoklu bayt tamsayı değerlerinden kaynaklanmış olmasıdır. küçük endian düzenine kaydedildi, ancak Mac'te büyük endian düzenine alındı ​​- ve yazılım platformlar arası taşınabilirlik düşünülerek oluşturulmadı. Günümüzde, gelişmiş geliştirici eğitimi ve gittikçe heterojen bilişim dünyamız sayesinde işler daha iyi.


2
İşlem hafıza alanına her şeyi bırakmak, güvenlik nedenleriyle de korkunç olurdu. Bir program gecesi hem 1) bazı genel veriler hem de 2) şifre, gizli olmayan veya özel anahtara sahip. Birincisini serileştirirken, ikincisi hakkında herhangi bir bilgi açıklamak istemez.
chi


15

Aldatmaca aslında zaten kelimenin kendisi ile tanımlanmaktadır: " seri izasyon".

Asıl soru şudur: keyfi bir şekilde karmaşık nesnelerin isteğe bağlı olarak karmaşık birbirine bağlı döngüsel olarak yönlendirilmiş bir grafiğini baytların doğrusal bir dizisi olarak nasıl temsil edebilirim?

Bir düşünün: Doğrusal bir dizi, her köşenin tam olarak bir gelen ve giden kenarı olduğu dejenere yönelimli bir grafik gibidir. . Ve bir bayt açıkça bir nesneden daha az karmaşıktır .

Yani, biz ve basit bayt keyfi karmaşık nesnelerden çok daha kısıtlı "grafiğinde" (aslında sadece bir liste) bir keyfi karmaşık grafikten giderken, bilgi dair makul görünmektedir edecektir 'biz safça bunu ve vermezsen, kaybolabilir t "yabancı" bilgileri bir şekilde kodlar. Serileştirmenin yaptığı da tam olarak budur: karmaşık bilgiyi basit bir doğrusal biçime kodlar.

YAML ile aşina iseniz , bir seri hale getirmedeki "aynı nesnenin farklı yerlerde görünebileceği" fikrini temsil etmenize izin veren bağlantı ve diğer ad özelliklerine bakabilirsiniz .

Örneğin, aşağıdaki grafiğe sahipseniz:

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

Bunu, YAML'deki gibi doğrusal yolların bir listesi olarak temsil edebilirsiniz:

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

Bunu bir bitişik liste veya bir bitişik matris olarak veya ilk elemanı bir düğüm kümesi olan ve ikinci elemanı bir düğüm çifti çifti olarak temsil eden bir çift olarak da gösterebilirsiniz, ancak tüm bu temsillerde, var olan düğümlere, yani genellikle bir dosya veya ağ akışında bulunmayan işaretçiler gibi geriye ve ileriye gönderme yolu . Sonunda sahip olduğunuz tek şey bayt.

(Hangi BTW, yukarıdaki YAML metin dosyasının kendisinin de "serileştirilmesi" gerektiği anlamına gelir, çeşitli karakter kodlamaları ve Unicode aktarma formatları bunun içindir. Bu, kesinlikle "serileştirme" değildir, çünkü sadece metin dosyası zaten seridir) / Doğrusal kod noktaları listesi, ancak bazı benzerlikler görebilirsiniz.)


13

Diğer cevaplar zaten karmaşık nesne grafiklerini ele alıyor, ancak ilkellerin serileştirilmesinin de önemsiz olduğuna işaret ediyor.

Beton için C ilkel tip adlarını kullanarak, şunları göz önünde bulundurun:

  1. Serileştiriyorum a long. Bir süre sonra ben de-serialize bunu, ama ... farklı bir platformda ve şimdi longise int64_tyerine int32_tben saklanır. Bu yüzden, sakladığım her türün tam boyutuna çok dikkat etmem ya da her alanın türünü ve boyutunu tanımlayan bazı meta verileri depolamam gerekir.

    Bu farklı platformun gelecekteki bir yeniden derlemeden sonra aynı platform olabileceğini unutmayın .

  2. Ben serileştiriyorum int32_t. Bir süre sonra onu seri hale getirdim, ancak ... farklı bir platformda ve şimdi değer bozuk. Ne yazık ki, değeri büyük bir endian platformuna kaydettim ve küçük bir endian platformuna yükledim. Şimdi, formatım için bir kural oluşturmam ya da her bir dosyanın / akışın / kodun isimlendirmesini açıklayan daha fazla meta veri eklemem gerekiyor. Ve tabii ki, aslında uygun dönüşümleri gerçekleştirin.

  3. Bir diziyi serileştiriyorum. Bu sefer bir platform charve UTF-8 ile bir wchar_tve UTF-16 kullanılır.

Dolayısıyla, makul kalitede seri hale getirmenin bitişik bellekteki ilkeller için bile önemsiz olmadığını iddia ediyorum. Belgelendirmeniz veya satır içi meta verilerle açıklamanız gereken çok sayıda kodlama kararı vardır.

Nesne grafikleri bunun üzerine başka bir karmaşıklık katmanı ekler.


6

Birden çok yönü var:

Aynı program tarafından okunabilirlik

Programınız verilerinizi bir şekilde bellekte bayt olarak sakladı. Ancak, işaretçiler daha küçük parçalar arasında gidip gelmekle birlikte, farklı kayıtlara rastgele dağılmış olabilirler. . Sadece bağlı bir tamsayı listesini düşünün. Her liste elemanı tamamen farklı bir yerde saklanabilir ve listeyi bir arada tutan tüm öğeler bir elemandan diğerine işaretçilerdir. Verileri olduğu gibi alacak ve aynı programı çalıştıran başka bir makineye kopyalamaya çalıştıysanız, sorunla karşılaşırsınız:

  1. Öncelikle ve en önemlisi, kayıt verilerinizin bir makinede saklandığını, başka bir makinede tamamen farklı bir şey için kullanılmış olabileceğini (birisi yığın bültenine göz atıyor ve tarayıcı zaten tüm bu hafızayı yedi) kullanıyor. Yani, sadece bu kayıtları geçersiz kılarsanız, güle güle tarayıcı. Bu nedenle, ikinci makinede sahip olduğunuz adreslere uyacak şekilde işaretçilerinizi yeniden yapılandırmanız gerekir. Aynı sorun, daha sonra aynı makinedeki verileri yeniden yüklemeye çalıştığınızda da ortaya çıkar.
  2. Bazı harici bileşenlerin yapınıza işaret etmesi veya yapınızın harici verilere işaret etmesi durumunda, siz iletmediyseniz? Her yerde segfaults! Bu hata ayıklama kabusu olur.

Başka bir program tarafından okunabilirlik

Verilerinizin uyması için başka bir makineye doğru adresleri vermeyi başardığınızı varsayalım. Verileriniz o makinede ayrı bir program tarafından işleniyorsa (farklı dil), bu program tamamen farklı bir temel veri anlayışına sahip olabilir. İşaretçiler içeren C ++ nesneleriniz olduğunu söyleyin, ancak hedef diliniz bu düzeydeki işaretçileri desteklemiyor. Yine, ikinci programdaki bu verileri ele almak için hiçbir temiz yol bulunmuyor. Bellekte bir miktar ikili veri bulunur, ancak daha sonra, verileri saran ek bir kod yazmanız ve bir şekilde onu hedef dilinizin çalışabileceği bir şeye dönüştürmeniz gerekir. Seriden arındırmaya benziyor, sadece başlangıç ​​noktanız ana belleğinizin etrafına dağılmış garip bir nesne, farklı kaynak diller için farklı. iyi tanımlanmış bir yapıya sahip bir dosya yerine. Aynı şey, elbette, işaretçiler içeren ikili dosyayı doğrudan yorumlamaya çalışırsanız, başka bir dilin bellekteki verileri temsil etmesi için mümkün olan her yol için çözümleyici yazmanız gerekir.

Bir insan tarafından okunabilirlik

Web tabanlı serileştirme için en belirgin modern serileştirme dillerinden ikisi (xml, json), bir insan tarafından kolayca anlaşılabilir. İkili bir goo yığını yerine, verilerin gerçek yapısı ve içeriği, verileri okumak için bir program olmadan bile açıktır. Bunun çok sayıda avantajı var:

  • daha kolay hata ayıklama -> Servis hattınızda bir sorun varsa, yalnızca bir servisten çıkan verilere bakar ve anlamlı olup olmadığını kontrol eder (ilk adım olarak); Dışa aktarma arayüzünüzü ilk sırada yazdığınızda, verilerin olması gerektiği gibi görünüp görünmediğini doğrudan görürsünüz.
  • arşivlenebilirlik: Verilerinizi saf bir ikili goo yığını olarak kullanıyorsanız ve onu yorumlamak için kullanılan programı kaybediyorsanız, verileri kaybedersiniz (ya da gerçekten orada bir şey bulmak için biraz zaman harcamanız gerekir); Serileştirilmiş verileriniz insan tarafından okunabiliyorsa, kolayca arşiv olarak kullanabilir veya kendi ithalatçınızı yeni bir program için programlayabilirsiniz.
  • Bu şekilde seri hale getirilmiş verilerin bildirim niteliği, aynı zamanda, bilgisayar sisteminden ve donanımından tamamen bağımsız olduğu anlamına gelir; tamamen farklı bir kuantum bilgisayara yükleyebilir veya alternatif gerçeklere sahip yabancı bir AI bulaştırabilir, böylece yanlışlıkla bir sonraki güneşe uçabilir (Emmerich eğer okursanız, bu fikri bir sonraki 4 Temmuz için kullanırsanız film)

Verilerim muhtemelen kayıtlarda değil, çoğunlukla ana bellektedir. Verilerim kayıtlara uyuyorsa, serileştirme zor bir meseledir. Sanırım bir kasanın ne olduğunu yanlış anladınız.
David Richerby

Gerçekten de, burada kayıt terimini çok gevşek kullandım. Ancak asıl nokta, verilerinizin kendi bileşenlerini tanımlamak veya başka verilere atıfta bulunmak için adres alanına işaretçiler içermesidir. Ana bellekte fiziksel bir kayıt veya sanal bir adres olması farketmez.
Frank Hopkins,

Hayır, "register" terimini tamamen yanlış kullandınız. Aradığınız kayıtlar, gerçek kayıtlara göre bellek hiyerarşisinin tamamen farklı bir kısmındadır.
David Richerby

6

Diğer cevapların söylediklerine ek olarak:

Bazen saf veri olmayan şeyleri serileştirmek istersiniz.

Örneğin, bir dosya tanıtıcısı veya bir sunucuya bağlantı düşünün. Dosya tanıtıcısı veya soketi bir olmasına rağmen int, bu sayı programın bir sonraki çalıştırılışında anlamsızdır. Bu tür tutamaçları içeren nesneleri uygun şekilde yeniden oluşturmak için dosyaları yeniden açmanız, bağlantıları yeniden oluşturmanız ve bunun başarısız olması durumunda ne yapacağınıza karar vermeniz gerekir.

Günümüzde birçok dil onBlah(), Javascript’teki bir işleyici gibi nesnelerde adsız işlevlerin saklanmasını desteklemektedir . Bu zordur, çünkü bu kod sırayla serileştirilmesi gereken ek veri parçalarına referanslar içerebilir. (Ve daha sonra kodların çapraz platform şeklinde serileştirilmesi sorunu var, ki bu, yorumlanmış diller için açıkça daha kolay.) Yine de, yalnızca bir dilin alt kümesi desteklenebilse bile, yine de oldukça yararlı olduğunu kanıtlayabilir. Pek çok seri hale getirme mekanizması kodu serileştirmeye çalışır , ancak serileştirme-javascript'e bakın .

Bir nesneyi serileştirmek istediğiniz ancak serileştirme mekanizmanız tarafından desteklenmeyen bir şey içerdiği durumlarda, kodu bunun etrafında çalışacak şekilde yeniden yazmanız gerekir. Örneğin, sınırlı sayıda olası işlev olduğunda, enumsiyonları isimsiz fonksiyonlar yerine kullanabilirsiniz.

Genellikle serileştirilmiş verilerin kısa olmasını istersiniz.

Ağ üzerinden veri gönderiyorsanız veya hatta diske kaydederseniz, boyutu küçük tutmak önemli olabilir. Bunu başarmanın en kolay yollarından biri, yeniden oluşturulabilecek bilgileri atmaktır (örneğin, önbellekleri atma, karma tabloları ve aynı verilerin alternatif gösterimlerini).

Elbette, programcının neyin kaydedileceğini ve nelerin atılacağını elle seçmesi ve nesne yeniden yaratıldığında şeylerin yeniden yapılmasını sağlaması gerekir.

Bir oyun kaydetme eylemini düşünün. Nesneler, grafik verileri, ses verileri ve diğer nesneler için çok fazla işaretçi içerebilir. Ancak bu şeylerin çoğu oyun veri dosyalarından yüklenebilir ve bir kaydetme dosyasında saklanması gerekmez. Bunu atmak zahmetli olabiliyor, bu yüzden çok az şey kalıyor. Zamanımdaki bazı tasarruf dosyalarını hex-edit yaptım ve metinsel öğelerin açıklamaları gibi açıkça gereksiz olan verileri keşfettim.

Bazen alan önemli değildir ama okunabilirlik - bu durumda bunun yerine bir ASCII formatı (muhtemelen JSON veya XML) kullanabilirsiniz.


3

Bir bayt dizisinin gerçekte ne olduğunu tanımlayalım. Bayt bir dizisi, negatif olmayan denilen bir tamsayı oluşur uzunluğu herhangi bir tamsayı eşleştirir ve keyfi bir fonksiyonu / yazışmalar i en azından sıfır ve en az bir uzunlukta bir bayt değerine (0 ile 255 arasında bir tam sayı) için.

Tipik bir programda ele aldığınız nesnelerin çoğu bu formda değildir, çünkü nesneler gerçekte RAM'deki farklı yerlerdeki birçok farklı bellek tahsisinden oluşur ve birbirinden milyonlarca byte öğeden ayrılabilir umrumda değil. Basit bir bağlantılı liste düşünün: listedeki her düğüm bir bayt dizisidir, evet, ancak düğümler bilgisayarınızın belleğinde birçok farklı konumda bulunur ve işaretçilerle bağlanırlar. Veya sadece değişken uzunluklu bir dize imleci olan basit bir yapı düşünün.

Veri yapılarını bir bayt dizisine serileştirmemizin nedeni genellikle onları diskte depolamak veya farklı bir sisteme (örneğin ağ üzerinden) göndermek istememizdir. Bir işaretçiyi diskte saklamaya veya farklı bir sisteme göndermeye çalışırsanız, bu işaretçiyi okuyan programda farklı bellek alanları kümesi olacağı için oldukça yararsız olacaktır.


1
Bunun bir dizilimin harika bir tanımı olduğundan emin değilim. Çoğu insan bir diziyi iyi bir dizilim olarak tanımlar: birbiri ardına bir şeyler dizisi. Tanımınıza göre int seq(int i) { if (0 <= i < length) return i+1; else return -1;}, bir dizidir. Peki bunu diskte nasıl saklayacağım?
David Richerby

1
Uzunluk 4 ise, içeriğe sahip dört baytlık bir dosya depolarım: 1, 2, 3, 4.
David Grayson

1
@DavidRicherby Onun tanımı "birbiri ardına sıralar" a eşittir, sezgisel tanımlamanızdan daha matematiksel ve kesin bir tanımdır. İşlevinizin bir dizi olmadığını unutmayın; çünkü bir dizinin olması için o işleve ve uzunluk olarak adlandırılan başka bir tam sayıya ihtiyacınız vardır .
user253751

1
@FreshAir Amacım, dizinin 1, 2, 3, 4, 5 olmasıdır. Yazdığım şey bir fonksiyondur . Bir işlev bir dizi değildir.
David Richerby

1
Diske bir işlev yazmanın basit bir yolu, daha önce önerdiğimdir: Her olası giriş için çıktıyı saklayın. Sanırım belki hala anlamadın ama ne söyleyeceğime emin değilim. Gömülü sistemlerde, pahalı işlevlerin sinsayı dizisi olan arama tablosuna dönüştürülmesinin yaygın olduğunu biliyor muydunuz ? İşlevinizin, umursadığımız girdiler için bununla aynı olduğunu biliyor muydunuz? Tam olarakint seq(n) { int a[] = [1, 2, 3, 4]; return a[n]; } neden dört baytlık dosyamın yetersiz bir temsil olduğunu söylüyorsunuz?
David Grayson

2

Karmaşıklıklar, verilerin karmaşıklığını yansıtır ve kendilerini nesneler. Bu nesneler gerçek dünya nesneleri veya yalnızca bilgisayar nesneleri olabilir. Cevap adına. Serileştirme, çok boyutlu nesnelerin doğrusal temsilidir. Parçalanmış RAM'den başka birçok sorun var.

12 beş boyutlu diziyi ve bazı program kodunu düzleştirebiliyorsanız, seri hale getirme, tüm bilgisayar programını (ve verileri) makineler arasında aktarmanıza olanak tanır. RMI / CORBA gibi dağıtılmış bilgi işlem protokolleri, veri ve programları aktarmak için yoğun serileştirmeyi kullanır.

Telefon faturanızı düşünün. Tüm çağrılarınızdan (dizelerin listesi), ödenecek tutardan (tam sayı) ve ülkeden oluşan tek bir nesne olabilir. Ya da telefon faturanız yukarıdan içeride olabilir ve adınıza bağlı ayrıntılı ayrıntılı telefon görüşmelerinden oluşabilir. Düzleştirilen her biri farklı görünecek, telefon şirketinizin yazılımın bu sürümünü nasıl yazdığını ve nesneye yönelik veritabanlarının neden hiç kullanılmadığını yansıtacaktır.

Yapının bazı kısımları hafızada bile olmayabilir. Eğer tembel önbelleğe alma işleminiz varsa, bir nesnenin bazı kısımları sadece bir disk dosyasına referans olarak verilebilir ve sadece o nesnenin o kısmına erişildiğinde yüklenir. Bu ciddi kalıcılık çerçevelerinde yaygındır. BLOB'lar iyi bir örnektir. Getty Images, Fidel Castro'nun devasa bir çok megabaytlık resmini ve görüntünün adı, kiralama maliyeti ve görüntünün kendisi gibi bazı meta verileri depolayabilir. 200 MB resmini, her seferinde belleğe yüklemek istemeyebilirsiniz, aslında ona bakmazsanız. Serileştirilmiş, tüm dosya 200 MB’nin üzerinde bir depolama alanı gerektirecektir.

Bazı nesneler hiç serileştirilemiyor bile. Java programlama ülkesinde, grafik ekranını veya fiziksel seri portu temsil eden bir programlama nesnesine sahip olabilirsiniz. Hiçbirinde serileştirme kavramı yok. Bağlantı noktanızı bir ağ üzerinden başka birine nasıl gönderirsiniz?

Parola / şifreleme anahtarları gibi bazı şeyler saklanmamalı veya iletilmemelidir. Bu şekilde etiketlenebilirler (geçici / geçici vb.) Ve seri hale getirme işlemi bunları atlayacak ancak RAM'de yaşayabilirler. Bu etiketleri atlamak, şifreleme anahtarlarının istemeden düz ASCII'de nasıl gönderildiğini / saklandığını gösterir.

Bu ve diğer cevaplar karmaşık olmasının nedenidir.


2

Karşılaştığım sorun şu: zaten bir bayt dizisi tarafından temsil edilen tüm değişkenler (int veya kompozit nesneler gibi ilkel olabilir) değil mi?

Evet onlar. Buradaki sorun, bu baytların düzeni. Basit int, 2, 4 veya 8 bit uzunluğunda olabilir. Büyük veya küçük endian içinde olabilir. İmzasız olabilir, 1'lerin tamamlayıcısı ile imzalanmış veya hatta negabinary gibi bazı süper egzotik bit kodlamalarda imzalanabilir.

intİkili belleği yalnızca bellekten atıp "seri hale getirilmiş" olarak adlandırırsanız, hemen hemen tüm bilgisayarı, işletim sistemini ve programınızı seri hale getirilebilmesi için eklemeniz gerekir. Veya en azından, bunların kesin bir açıklaması.

Peki seri hale getirmeyi böylesine derin bir konu yapan nedir? Bir değişkeni serileştirmek için, bu baytları bellekte alıp bir dosyaya yazamaz mıyız? Hangi inceliklerini kaçırdım?

Basit bir nesnenin seri hale getirilmesi hemen hemen bazı kurallara göre yazıyor. Bu kurallar bol ve her zaman açık değildir. Örneğin, bir xs:integerXML, taban-10 ile yazılmıştır. Temel 16 değil, temel 9 değil, ancak 10. Gizli bir varsayım değil, gerçek bir kuraldır. Ve bu tür kurallar seri hale getirmeyi seri hale getirir. Çünkü, hemen hemen programınızın bit düzeninde bellekte kural yoktur .

Bu sadece bir buzdağının görünen ucuydu. Bir C: Öyle bu basit ilkel bir dizisinin bir örneğini sunar struct. Bunu düşünebilirsin

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

belirli bir bilgisayarda + OS'da tanımlanmış bir bellek düzeni var mı? Öyle değil. Mevcut #pragma packayara bağlı olarak , derleyici alanları doldurur. 32 bit derlemenin varsayılan ayarlarında, her ikisi shortsde 4 baytla doldurulur, böylece structbellekte 3 alan 4 bayt olur. Şimdi, sadece shortbunun 16 bit uzunluğunda olduğunu belirtmeniz gerekmez , 1'in negatif, büyük veya küçük endian dilinde yazılmış bir tamsayıdır. Ayrıca, programınızın derlendiği yapı paketleme ayarını da yazmanız gerekir.

Serileştirmenin konusu budur: bir dizi kural koymak ve bunlara bağlı kalmak.

Bu kurallar daha sonra vb insan okunabilirliği gibi ek özelliklerle, sürüm, geriye dönük uyumluluk ve hata düzeltme, (değişken uzunluk listeleri veya doğrusal olmayan veriler gibi) biraz daha karmaşık yapıları kabul etmek genişletilmiş Ama tek yazmaktan bile olabilir intzaten eğer yeterince karmaşıktır yalnızca güvenle geri okuyabileceğinizden emin olmak istiyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.