Comprendre la sérialisation


38

Je suis un ingénieur en logiciel et après une discussion avec des collègues, j'ai réalisé que je ne maîtrisais pas bien la sérialisation du concept. Si je comprends bien, la sérialisation est le processus de conversion d'une entité, telle qu'un objet dans la POO, en une séquence d'octets, de sorte que ladite entité puisse être stockée ou transmise pour un accès ultérieur (processus de "désérialisation").

Le problème que j'ai est le suivant: toutes les variables (qu'il s'agisse de primitives intou d'objets composites) ne sont-elles pas déjà représentées par une séquence d'octets? (Bien sûr, car ils sont stockés dans des registres, mémoire, disque, etc.)

Alors, qu'est-ce qui fait de la sérialisation un sujet aussi profond? Pour sérialiser une variable, ne pouvons-nous pas simplement prendre ces octets en mémoire et les écrire dans un fichier? Quelles subtilités ai-je ratées?


21
La sérialisation peut être triviale pour les objets contigus . Lorsque la valeur de l'objet est représentée sous la forme d'un graphe de pointeur , les choses deviennent beaucoup plus compliquées, surtout si ce graphe comporte des boucles.
chi

1
@chi: Votre première phrase est un peu trompeuse étant donné que la contiguïté n'est pas pertinente. Vous avez peut-être un graphique continu en mémoire et qui ne vous aiderait toujours pas à le sérialiser puisqu'il vous reste à (a) détecter qu'il est effectivement contigu et à (b) corriger les pointeurs à l'intérieur. Je viens de dire la deuxième partie de ce que vous avez dit.
Mehrdad

@Mehrdad Je conviens que mon commentaire n'est pas tout à fait précis, pour les raisons que vous avez mentionnées. Peut-être que l'utilisation d'un pointeur ou d'un pointeur est une meilleure distinction (même si elle n'est pas complètement exacte non plus)
chi

7
Vous devez également vous préoccuper de la représentation sur le matériel. Si je sérialise un int 4 bytessur mon PDP-11, puis que je tente de lire ces mêmes quatre octets en mémoire sur mon macbook, ils ne sont pas le même numéro (à cause de Endianes). Vous devez donc normaliser les données en une représentation que vous pouvez décoder (il s’agit d’une sérialisation). La façon dont vous sérialisez les données a également des compromis vitesse / flexibilité lisible par l'homme / machine.
Martin York

Que faire si vous utilisez Entity Framework avec de nombreuses propriétés de navigation profondément connectées? Dans un cas, vous pouvez vouloir sérialiser une propriété de navigation, mais dans un autre laissez la valeur nulle (car vous rechargerez cet objet à partir de la base de données en fonction de l'ID figurant dans votre objet parent sérialisé). Ceci n'est qu'un exemple. Il y a beaucoup de.
ErikE

Réponses:


40

Si vous avez une structure de données compliquée, sa représentation en mémoire peut normalement être dispersée dans la mémoire. (Pensez à un arbre binaire, par exemple.)

En revanche, lorsque vous souhaitez l'écrire sur le disque, vous souhaiterez probablement une représentation sous la forme d'une séquence (espérons-le courte) d'octets contigus. C'est ce que la sérialisation fait pour vous.


27

Le problème que j'ai est le suivant: toutes les variables (que ce soit des primitives telles que int ou des objets composites) ne sont-elles déjà représentées par une séquence d'octets? (Bien sûr, car ils sont stockés dans des registres, mémoire, disque, etc.)

Alors, qu'est-ce qui fait de la sérialisation un sujet aussi profond? Pour sérialiser une variable, ne pouvons-nous pas simplement prendre ces octets en mémoire et les écrire dans un fichier? Quelles subtilités ai-je ratées?

Considérons un graphe d'objet en C avec des nœuds définis comme ceci:

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

Au moment de l'exécution, le Nodegraphe d' objet entier était dispersé dans l'espace mémoire et le même nœud pouvait être pointé à partir de nombreux nœuds différents.

Vous ne pouvez pas simplement vider la mémoire dans un fichier / flux / disque et l'appeler sérialisé car les valeurs du pointeur (qui sont des adresses de mémoire) ne peuvent pas être désérialisées (car ces emplacements de mémoire sont peut-être déjà occupés lorsque vous chargez la sauvegarde. en mémoire). Un autre problème avec le simple vidage de mémoire est que vous allez finir par stocker toutes sortes de données non pertinentes et d’espace inutilisé - sur un processus x86, jusqu’à 4 Go de mémoire, et un système d’exploitation ou une unité de gestion n’a qu’une idée générale de ce que la mémoire est réellement. significatif ou non (en fonction des pages de mémoire affectées à un processus), donc Notepad.exevider 4 Go d'octets bruts sur mon disque chaque fois que je veux enregistrer un fichier texte semble un peu inutile.

Un autre problème concerne le contrôle de version: que se passe-t-il si vous sérialisez votre Nodegraphique le premier jour, puis le deuxième jour, vous ajoutez un autre champ à Node(comme une autre valeur de pointeur ou une valeur primitive), puis le troisième jour, vous désérialisez votre fichier jour 1?

Vous devez également considérer d'autres choses, comme l'endianité. L'une des principales raisons pour lesquelles les fichiers MacOS et IBM / Windows / PC étaient incompatibles dans les années 1980 et 1990, alors qu'ils étaient apparemment conçus par les mêmes programmes (Word, Photoshop, etc.) était due aux valeurs entières multi-octets x86 / PC ont été sauvegardés dans l’ordre little-endian, mais dans l’ordre big-endian sur le Mac - et le logiciel n’a pas été conçu pour une portabilité multiplate-forme. De nos jours, les choses vont mieux grâce à une meilleure formation des développeurs et à notre monde informatique de plus en plus hétérogène.


2
Dumping tout dans la mémoire de processus serait également horrible pour des raisons de sécurité. Une nuit de programme a en mémoire à la fois 1) des données publiques et 2) un mot de passe, une clé secrète ou une clé privée. Lors de la sérialisation du premier, on ne veut révéler aucune information sur le dernier.
chi


15

Le fait est délicat déjà décrit dans le mot lui - même: « série isation ».

La question qui se pose est fondamentale: comment puis-je représenter un graphe orienté cyclique interconnecté de manière arbitraire et complexe d’objets complexes de manière arbitraire en tant que séquence linéaire d’octets?

Pensez-y: une séquence linéaire ressemble un peu à un graphe dirigé dégénéré où chaque sommet a exactement un bord entrant et sortant (sauf le "premier sommet" qui n'a pas de bord entrant et le "dernier sommet" qui n'a pas de bord sortant) . Et un octet est évidemment moins complexe qu'un objet .

Il semble donc raisonnable de passer d’un graphe arbitrairement complexe à un "graphe" beaucoup plus restreint (en réalité une liste) et d’objets arbitrairement complexes à de simples octets: les informations seront perdues si nous le faisons naïvement et si nous ne le faisons pas. t coder l’information "étrangère" d’une certaine manière. Et c'est exactement ce que fait la sérialisation: coder les informations complexes dans un format linéaire simple.

Si vous connaissez bien YAML , vous pouvez consulter les fonctionnalités d' ancrage et d' alias qui vous permettent de représenter l'idée que "le même objet peut apparaître à différents endroits" dans une sérialisation.

Par exemple, si vous avez le graphique suivant:

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

Vous pouvez représenter cela comme une liste de chemins linéaires dans YAML comme ceci:

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

Vous pouvez également le représenter sous forme de liste de contiguïté, ou de matrice de contiguïté, ou de paire dont le premier élément est un ensemble de nœuds et dont le second élément est un ensemble de paires de nœuds, mais dans toutes ces représentations, vous devez disposer un moyen de faire référence en arrière et en avant aux nœuds existants , c'est-à-dire aux pointeurs , que vous n'avez généralement pas dans un fichier ou un flux de réseau. Tout ce que vous avez, à la fin, ce sont des octets.

(BTW signifie que le fichier texte YAML ci-dessus doit lui aussi être "sérialisé", c’est ce à quoi servent les divers encodages de caractères et formats de transfert Unicode… ce n’est pas strictement une "sérialisation", c’est un encodage, car le fichier texte est déjà une série / liste linéaire des points de code, mais vous pouvez voir quelques similitudes.)


13

Les autres réponses concernent déjà les graphes d'objets complexes, mais il convient de souligner que la sérialisation des primitives est également non triviale.

En utilisant les noms de type primitifs C pour plus de précision, considérez:

  1. Je sérialiser un long. Quelque temps plus tard , je désérialiser, mais ... sur une autre plate - forme, et maintenant longest int64_tplutôt que int32_tj'emmagasinés. Donc, je dois soit faire très attention à la taille exacte de chaque type que je stocke, soit stocker des métadonnées décrivant le type et la taille de chaque champ.

    Notez que cette plate - forme différente pourrait être la même plate-forme après une future recompilation.

  2. Je sérialiser un int32_t. Quelque temps plus tard, je le désérialise, mais ... sur une plate-forme différente, et maintenant la valeur est corrompue. Malheureusement, j'ai sauvegardé la valeur sur une plate-forme big-endian et l'ai chargée sur une plate-forme little-endian. Maintenant, je dois établir une convention pour mon format ou ajouter plus de métadonnées décrivant la finalité de chaque fichier / flux / quoi que ce soit. Et, bien sûr, effectuez les conversions appropriées.

  3. Je sérialise une chaîne. Cette fois, une plate-forme utilise charet UTF-8, et une wchar_tet UTF-16.

Je dirais donc que la sérialisation de qualité raisonnable n'est pas triviale, même pour les primitives en mémoire contiguë. Vous devez prendre de nombreuses décisions d’encodage pour documenter ou décrire avec des métadonnées en ligne.

Les graphiques d'objet ajoutent une couche de complexité supplémentaire.


6

Il y a plusieurs aspects:

Lisibilité par le même programme

Votre programme a stocké vos données d’une manière ou d’une autre sous forme d’octets dans la mémoire. Mais elle peut être dispersée de manière arbitraire dans différents registres, avec des pointeurs allant et venir entre ses plus petites parties . Il suffit de penser à une liste d’entiers liés. Chaque élément de la liste peut être stocké à un endroit totalement différent et tout ce qui maintient la liste est constitué par les pointeurs d'un élément à l'autre. Si vous preniez ces données telles quelles et tentiez de les copier sur une autre machine exécutant le même programme, vous rencontreriez des problèmes:

  1. D'abord et avant tout, les adresses de registre dans lesquelles vos données sont stockées sur une machine peuvent déjà être utilisées pour quelque chose de complètement différent sur une autre machine (quelqu'un est en train de parcourir l'échange de piles et le navigateur a déjà utilisé toute cette mémoire). Donc, si vous remplacez simplement ces registres, adieu navigateur. Ainsi, vous devrez réorganiser les pointeurs de la structure pour les adapter aux adresses libres de la deuxième machine. Le même problème se pose lorsque vous essayez de recharger les données sur le même ordinateur ultérieurement.
  2. Et si certains composants externes pointaient dans votre structure ou si votre structure contenait des pointeurs vers des données externes, vous ne les transmettiez pas? Des Segfaults partout! Cela deviendrait un cauchemar de débogage.

Lisibilité par un autre programme

Supposons que vous parveniez à attribuer les bonnes adresses sur une autre machine, pour que vos données puissent s'intégrer. Si vos données sont traitées par un programme séparé sur cette machine (langue différente), ce programme peut avoir une compréhension de base des données totalement différente. Disons que vous avez des objets C ++ avec des pointeurs, mais que votre langage cible ne prend même pas en charge les pointeurs de ce niveau. Encore une fois, vous vous retrouvez avec aucun moyen propre de traiter ces données dans le deuxième programme. Vous vous retrouvez avec des données binaires en mémoire, mais vous devez ensuite écrire du code supplémentaire qui enveloppe les données et les traduit d'une manière ou d'une autre en quelque chose que votre langue cible peut utiliser. Cela ressemble à de la désérialisation, mais votre point de départ est maintenant un objet étrange éparpillé dans votre mémoire principale, qui est différent pour différentes langues sources, au lieu d'un fichier avec une structure bien définie. Même chose, bien sûr, si vous essayez d'interpréter directement le fichier binaire qui inclut des pointeurs - vous devez écrire des analyseurs pour chaque manière possible qu'une autre langue peut représenter des données en mémoire.

Lisibilité par un humain

Deux des langages de sérialisation modernes les plus en vue pour la sérialisation Web (xml, json) sont facilement compréhensibles par un humain. Au lieu d'une pile binaire de goo, la structure et le contenu réels des données sont clairs, même sans programme de lecture des données. Cela présente de multiples avantages:

  • débogage plus facile -> s'il y a un problème dans votre pipeline de services, il vous suffit de regarder les données qui sortent d'un service et de vérifier si cela a un sens (dans un premier temps); vous voyez également directement si les données vous semblent justes, lorsque vous écrivez votre interface d'exportation en premier lieu.
  • archivabilité: si vous avez vos données sous la forme d'une pile binaire pure et que vous perdez le programme destiné à l'interpréter, vous perdez les données (ou vous devrez passer un certain temps à trouver quelque chose dedans); si vos données sérialisées sont lisibles par l'homme, vous pouvez facilement les utiliser comme archives ou programmer votre propre importateur pour un nouveau programme.
  • le caractère déclaratif des données sérialisées de cette manière signifie également qu’elles sont totalement indépendantes du système informatique et de son matériel; vous pourriez le charger dans un ordinateur quantique de construction totalement différente ou infecter une IA étrangère avec des faits alternatifs pour qu'il vole accidentellement au soleil (Emmerich si vous lisez ceci, une référence serait bien si vous utilisez cette idée pour le 4 juillet prochain. film)

Mes données sont probablement principalement dans la mémoire principale, pas dans les registres. Si mes données tiennent dans des registres, la sérialisation est à peine un problème. Je pense que vous avez mal compris ce qu'est un registre.
David Richerby

En effet, j’ai utilisé le terme registre de manière trop vague ici. Mais le point principal est que vos données peuvent contenir des pointeurs sur l'espace d'adressage pour identifier leurs propres composants ou faire référence à d'autres données. Peu importe qu'il s'agisse d'un registre physique ou d'une adresse virtuelle dans la mémoire principale.
Frank Hopkins

Non, vous avez utilisé le terme "enregistrer" de manière totalement incorrecte. Les choses que vous appelez des registres se trouvent dans une partie complètement différente de la hiérarchie de la mémoire par rapport aux registres réels.
David Richerby

6

En plus de ce que les autres réponses ont dit:

Parfois, vous souhaitez sérialiser des éléments qui ne sont pas des données pures.

Par exemple, pensez à un descripteur de fichier ou à une connexion à un serveur. Même si le descripteur de fichier ou le socket est un int, ce nombre n'a pas de sens lors de la prochaine exécution du programme. Pour recréer correctement les objets contenant des descripteurs, vous devez rouvrir les fichiers, recréer les connexions et décider quoi faire en cas d'échec.

De nos jours, de nombreuses langues permettent de stocker des fonctions anonymes dans des objets, par exemple un onBlah()gestionnaire en Javascript. Cela est difficile car un tel code peut contenir des références à des éléments de données supplémentaires qui doivent à leur tour être sérialisés. (Et puis il y a le problème de la sérialisation du code sur plusieurs plates-formes, ce qui est évidemment plus facile pour les langages interprétés.) Néanmoins, même si seul un sous-ensemble du langage peut être supporté, cela peut encore s'avérer très utile. Peu de mécanismes de sérialisation tentent de sérialiser le code, mais voir -vous à serialize-javascript .

Dans les cas où vous souhaitez sérialiser un objet mais qu'il contient quelque chose qui n'est pas pris en charge par votre mécanisme de sérialisation, vous devez réécrire le code de manière à contourner le problème. Par exemple, vous pouvez utiliser des énumérations à la place de fonctions anonymes lorsqu'il existe un nombre fini de fonctions possibles.

Souvent, vous souhaitez que les données sérialisées soient concises.

Si vous envoyez des données sur le réseau ou même les stockez sur un disque, il peut être important de conserver une taille réduite. L'un des moyens les plus simples d'y parvenir consiste à supprimer les informations pouvant être reconstruites (par exemple, en supprimant les caches, les tables de hachage et les représentations alternatives des mêmes données).

Bien sûr, le programmeur doit sélectionner manuellement ce qui doit être enregistré et ce qui doit être supprimé, et s’assurer que tout est reconstruit lors de la recréation de l’objet.

Pensez à l'acte de sauver une partie. Les objets peuvent contenir de nombreux pointeurs vers des données graphiques, des données audio et d'autres objets. Mais la plupart de ces éléments peuvent être chargés à partir des fichiers de données de jeu et n'ont pas besoin d'être stockés dans un fichier de sauvegarde. Le rejeter peut être laborieux et il reste souvent peu de choses. J'ai jeté des disques sur certains fichiers de sauvegarde à mon époque et découvert des données clairement redondantes, comme des descriptions d'éléments textuels.

Parfois, l’espace n’est pas important, mais la lisibilité l’est. Dans ce cas, vous pouvez utiliser plutôt un format ASCII (éventuellement JSON ou XML).


3

Définissons ce qu'est une séquence d'octets. Une séquence d'octets est constituée d'un entier non négatif appelé longueur et d'une fonction / correspondance arbitraire mappant tout entier i d' au moins zéro et inférieur à la longueur. à une valeur d'octet (entier compris entre 0 et 255).

La plupart des objets que vous traitez dans un programme typique ne se présentent pas sous cette forme, car ils sont en fait constitués de nombreuses allocations de mémoire différentes situées à différents endroits dans la RAM et peuvent être séparées les unes des autres par des millions d'octets. ne t'inquiète pas. Pensez simplement à une liste chaînée: chaque nœud de la liste est une séquence d'octets, mais les nœuds se trouvent à de nombreux emplacements différents dans la mémoire de votre ordinateur et sont connectés à des pointeurs. Ou pensez simplement à une structure simple qui a un pointeur sur une chaîne de longueur variable.

La raison pour laquelle nous voulons sérialiser les structures de données en une séquence d'octets est généralement due au fait que nous voulons les stocker sur un disque ou les envoyer à un autre système (par exemple sur le réseau). Si vous essayez de stocker un pointeur sur le disque ou de l'envoyer vers un autre système, cela sera plutôt inutile car le programme qui lit ce pointeur disposera d'un ensemble différent de zones de mémoire.


1
Je ne suis pas sûr que ce soit une excellente définition d'une séquence. La plupart des gens définiraient une séquence comme étant, bien, une séquence: une ligne de choses les unes après les autres. Par votre définition, int seq(int i) { if (0 <= i < length) return i+1; else return -1;}est une séquence. Alors, comment vais-je stocker cela sur le disque?
David Richerby

1
Si la longueur est 4, je stocke un fichier de quatre octets avec le contenu: 1, 2, 3, 4.
David Grayson

1
@DavidRicherby Sa définition est équivalente à "une ligne de choses les unes après les autres", c'est juste une définition plus mathématique et précise que votre définition intuitive. Notez que votre fonction n'est pas une séquence car pour avoir une séquence, vous avez besoin de cette fonction et d' un autre entier appelé longueur.
user253751

1
@FreshAir Mon point est que la séquence est 1, 2, 3, 4, 5. La chose que j'ai écrite est une fonction . Une fonction n'est pas une séquence.
David Richerby

1
Un moyen simple d’écrire une fonction sur le disque est celui que j’avais déjà proposé: pour chaque entrée possible, stockez la sortie. Je pense que vous ne comprenez peut-être toujours pas, mais je ne sais pas quoi dire. Saviez-vous que dans les systèmes embarqués, il est courant de convertir des fonctions coûteuses comme sinune table de correspondance, qui est une séquence de nombres? Saviez-vous que votre fonction est la même que celle-ci pour les intrants qui nous intéressent? int seq(n) { int a[] = [1, 2, 3, 4]; return a[n]; } Pourquoi exactement dites-vous que mon fichier de quatre octets est une représentation inadéquate?
David Grayson

2

Les subtilités reflètent les subtilités des données et des objets eux-mêmes. Ces objets peuvent être des objets du monde réel ou des objets uniquement informatiques. La réponse est dans le nom. La sérialisation est la représentation linéaire des objets multidimensionnels. Il existe de nombreux problèmes autres que la RAM fragmentée.

Si vous pouvez aplatir 12 tableaux à cinq dimensions et certains codes de programme, la sérialisation vous permet également de transférer un programme informatique complet (et des données) entre des machines. Les protocoles informatiques distribués tels que RMI / CORBA utilisent largement la sérialisation pour transférer des données et des programmes.

Considérez votre facture de téléphone. Il peut s'agir d'un objet unique, composé de tous vos appels (liste de chaînes), du montant à payer (entier) et du pays. Ou bien votre facture de téléphone pourrait être à l’envers de ce qui précède et consister en des appels téléphoniques détaillés détaillés liés à votre nom. Chaque image aplatie sera différente, reflétant comment votre compagnie de téléphone a écrit cette version de son logiciel et la raison pour laquelle les bases de données orientées objet n'ont jamais pris son essor.

Certaines parties d'une structure peuvent même ne pas être en mémoire du tout. Si vous utilisez une mise en cache paresseuse, certaines parties d'un objet peuvent uniquement être référencées à un fichier de disque et ne sont chargées que lorsque vous accédez à cette partie de cet objet particulier. Ceci est courant dans les cadres de persistance graves. Les BLOBs sont un bon exemple. Getty Images peut stocker une grande image de plusieurs mégaoctets de Fidel Castro et des métadonnées telles que le nom de l'image, le coût de la location et l'image elle-même. Vous ne voudrez peut-être pas charger l’image de 200 Mo en mémoire à chaque fois, sauf si vous le regardez réellement. Sérialisé, le fichier entier nécessiterait plus de 200 Mo de stockage.

Certains objets ne peuvent même pas être sérialisés. Au pays de la programmation Java, vous pouvez avoir un objet de programmation représentant l'écran graphique ou un port série physique. Il n'y a pas de véritable concept de sérialisation de l'un ou l'autre. Comment enverriez-vous votre port à quelqu'un d'autre via un réseau?

Certaines choses telles que les mots de passe / clés de chiffrement ne doivent pas être stockées ou transmises. Ils peuvent être étiquetés en tant que tels (volatiles / transitoires, etc.) et le processus de sérialisation les ignorera, mais ils peuvent vivre dans la RAM. L'omission de ces balises explique comment des clés de chiffrement sont envoyées / stockées par inadvertance en ASCII simple.

Ceci et les autres réponses sont la raison pour laquelle c'est compliqué.


2

Le problème que j'ai est le suivant: toutes les variables (que ce soit des primitives telles que int ou des objets composites) ne sont-elles déjà représentées par une séquence d'octets?

Oui, ils sont. Le problème ici est la disposition de ces octets. Un simple intpeut avoir une longueur de 2, 4 ou 8 bits. Il peut être en gros ou petit endian. Il peut être non signé, signé avec le complément à 1 ou même dans un codage de bits super exotique comme le négatif.

Si vous intextrayez simplement les fichiers binaires de la mémoire et que vous appelez cela "sérialisé", vous devez connecter un ordinateur au complet, le système d'exploitation et votre programme pour qu'il soit désérialisable. Ou du moins, une description précise d'eux.

Alors, qu'est-ce qui fait de la sérialisation un sujet aussi profond? Pour sérialiser une variable, ne pouvons-nous pas simplement prendre ces octets en mémoire et les écrire dans un fichier? Quelles subtilités ai-je ratées?

La sérialisation d'un objet simple revient à l'écrire selon certaines règles. Ces règles sont nombreuses et pas toujours évidentes. Par exemple, un xs:integerfichier XML est écrit en base 10. Pas en base 16, ni en base 9, mais en 10. Ce n'est pas une hypothèse cachée, c'est une règle réelle. Et de telles règles font de la sérialisation une sérialisation. Parce qu'en gros , il n'y a pas de règles en mémoire sur la disposition des bits de votre programme .

Ce n'était que la pointe de l'iceberg. Prenons un exemple d’une séquence de ces primitives les plus simples: un Cstruct . Vous pourriez penser que

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

a une disposition de la mémoire définie sur un ordinateur + OS? Eh bien, ce n'est pas le cas. Selon le #pragma packréglage actuel , le compilateur remplira les champs. Sur les paramètres par défaut de la compilation 32 bits, les deuxshorts seront complétés à 4 octets, de sorte qu'ils structauront en réalité 3 champs de 4 octets en mémoire. Alors maintenant, vous devez non seulement spécifier une shortlongueur de 16 bits, mais aussi un entier, écrit en complément à 1 négatif, grand ou petit. Vous devez également écrire le paramétrage de la structure avec lequel votre programme a été compilé.

C'est à peu près ce en quoi consiste la sérialisation: créer un ensemble de règles et s'y tenir.

Ces règles peuvent ensuite être étendues pour accepter des structures encore plus sophistiquées (telles que des listes à longueur variable ou des données non linéaires), des fonctionnalités supplémentaires telles que la lisibilité humaine, la gestion des versions, la compatibilité ascendante et la correction des erreurs, etc. Mais même en écrire une seule intest déjà assez compliquée. Je veux seulement m'assurer que vous pourrez le relire de manière fiable.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.