6
votes

Comment analyser un tableau d'octets dans un objet?

Je lis, je lis des données binaires (soit par flux réseau, soit à partir de fichiers) prédéfinies il y a plusieurs années. Je lis actuellement ces données en le lisant dans une matrice d'octet, puis convertissez le tableau dans les champs dont j'ai besoin avec system.bitconverter . Inutile de dire que ceci est le chronogène et l'erreur sujette.

J'aimerais pouvoir utiliser iserializable , mais je ne vois pas comment cela peut être mis en œuvre pour une structure prédéfinie.

J'espère que les indicateurs sur la manière d'améliorer ma stratégie actuelle ...


0 commentaires

4 Réponses :


4
votes

Un moyen est de créer un MemoryStream autour du tableau d'octets, puis utilisez un < Code> BinaryReader . Qui vous permet d'analyser les valeurs primitives, etc. très facilement.

Cependant, cela dépend de la question de savoir si le Endianness des données est approprié. J'ai un endianbinarinaader classe dans MISCUTIL qui peut vous aider si le Intégré n'est pas approprié.


7 commentaires

+1: J'aime ça, mais je tiens à beaucoup d'analyser par rapport à la solution suggérée par @Joe.


@rozon: Oui, mais cela maintient tout explicite plutôt que de compter sur une représentation en mémoire. Je suis personnellement désireux de faire des formats de sérialisation très explicites et donc facilement documentés.


@Jon: Les formats sont très explicites et définis par un système d'automate. La représentation en mémoire .NET est garantie par les maréhalas et le champ de terrain. Quand ils sont définis corrects, je peux garder la sérialisation et la désérialisation en synchronisation avec moins de code (je pense?).


@rozon: Et comment allez-vous spécifier l'endoinness lorsqu'il s'agit de marshaller directement dans la mémoire, tout comme un exemple de la façon dont cela peut aller mal?


@Jon: Je vois ton point. Comment vont-ils différer de vitesse? J'imagine que la solution de @joe est plus rapide, mais j'apprends toujours.


@rozon: Oui, faire des choses explicitement sera probablement plus lente que de se glisser dans la mémoire. Il peut même être un ordre de grandeur plus lent ... mais cela ne signifie pas que la différence sera importante dans une application réelle. Cela dépend entièrement de ce que vous faites.


@Jon: Je regarde les données d'un système de journalisation des données "réeltime", mais je doute que l'analyse fera la différence. Si le temps permet, je vais aussi essayer votre solution.



1
votes

J'espère que cette aide:

  //set your byte data instead of null
        byte[] data = null;

        MemoryStream stream = new MemoryStream();
        stream.Write(data,0,data.Length);

        BinaryFormatter formatter = new BinaryFormatter();

        Type s1 = (Type)formatter.Deserialize(stream);


1 commentaires

Et comment cela peut-il installer une structure de données prédéfinie?



2
votes

Les cours et méthodes interoptés du maréchal (nommément ptrtostructure et structoptr) peuvent également aider ici aussi. Voir: http://msdn.microsoft.com/en-us/library/4ca6d5z7 .aspx


0 commentaires

5
votes

Rozon, j'ai eu exactement le même problème, et j'étais sur le point d'abandonner la solution jusqu'à ce que je trouvais cette question ici et de lire la réponse de Joe. Joe mentionne l'objet maréchal pour déplacer des données entre les Memory et un objet géré ... Voici ce que j'ai fait, et qu'est-ce que je travaillais comme magique pour moi ... Si vous ne l'avez pas déjà compris. , voici toute une rupture de ce que j'ai fait, et comment je l'ai eu pour travailler .. (Merci Joe!) ...

Premièrement, vous devez être capable de créer une instance gérée de votre structure. Cela ne devrait pas être trop difficile, cela signifie simplement beaucoup d'attributs supplémentaires sur votre structure.

Par exemple, voici une structure de données contenant des informations sur un serveur. Bien sûr, les tailles de chaîne ne sont pas précises, assurez-vous donc que vos tailles de chaîne sont! xxx

également, assurez-vous que vous utilisez le bon caractère, dans le cas où il était possible. compilé pour utiliser Unicode, vous devez vous assurer que le Charset reflète que.

Maintenant, voici la partie froide ...

Pour obtenir la taille de la structure (et la taille de la mémoire tampon que vous devez le tenir), vous n'avez besoin que d'utiliser: xxx

et, avec cela, vous pouvez maintenant faire ce que vous faites pour obtenir ces données livrées Pour vous, (que je suppose que vous avez déjà tout ce qui figurait sur ...) Et puis la magie peut commencer. Ce que nous faisons, alloue un bloc de mémoire non gérée, puis copiez le tampon dans le bloc de la mémoire, puis copiez-le dans notre structure et libérez le bloc de mémoire non géré. Cela peut facilement être placé dans une fonction d'extension pouvant fonctionner sur n'importe quel octet [], vous permettant d'appeler quelque chose comme: xxx

Le code suivant est ce qui a fonctionné pour moi. Oh, et n'oubliez pas de mettre l'essai / attraper / enfin bloque autour de cela dans le code de production ... xxx

et là, vous l'avez! Cela évite toutes les informations d'en-tête supplémentaires incluses lorsque vous utilisez la sérialisation et, il s'agit de la seule façon de trouver des données précises sur la taille d'une structure gérée. Je suis sûr qu'il y a peut-être d'autres façons de faire cela, mais jusqu'à présent, c'est le meilleur que j'ai trouvé, après environ 5 jours de recherche, piratage, de recherche, de débogage, de piratage et de recherche d'autres ... :) < / p>

Si cela fonctionne pour vous, faites-moi savoir ... Je suis curieux de voir s'il corrige votre problème aussi.


2 commentaires

Ça marche pour moi. M'a sauvé beaucoup de temps de mettre en œuvre et il est facile de rester maintenu. +1 pour donner beaucoup plus de code que Joe.


@rozon - c'est génial! Je suis content que vous ayez aidé à vous aider. N'oubliez pas que Skeet soulève de bons points sur l'endianesse, mais si vous ne traitez pas de données pouvant éventuellement provenir d'une grande source d'Endian, vous n'avez pas à vous soucier de cela. Tant que les données entrantes, c'est exactement ce dont vous avez besoin de sortir, cela fonctionnera pour vous. Soyez juste prudent avec les différents types de chaîne, etc ... ils peuvent vraiment vous bousiller si vous les fermez de manière incorrecte ...