IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Lire les données binaires présentes en mémoire


Sujet :

C#

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2011
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 81
    Points : 36
    Points
    36
    Par défaut Lire les données binaires présentes en mémoire
    Hello world !

    Je voudrais simplement récupérer les données binaires stockées sur la RAM lorsque je déclare un tableau de byte[]. Alors que dans ces cas, les valeurs affichées sont convertit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    byte[] myArrayByte = new byte[] { 0xAA, 0xBB, 0xCC, 0x01, 0x02, 0x03  };
    foreach (byte currentByte in myArrayByte)
        Console.Write(currentByte+ "-"); // return 170-187-204-1-2-3
     
    foreach (int currentByte in myArrayByte)
        Console.Write(currentByte+ "-"); // return 170-187-204-1-2-3
     
    foreach (char currentByte in myArrayByte)
        Console.Write(currentByte+ "-"); // return la correspondance des nombre dans la table ASCII
    Je voudrais juste récupérer les vrais bits stockés en mémoire, sans convertion de type. Un peu comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    byte[] myArrayByte = new byte[] { 0xAA, 0xBB, 0xCC, 0x01, 0x02, 0x03 };
    foreach (string currentByte in myArrayByte)
        Console.Write(currentByte+ "-"); 
     
    // return :10101010-10111011-11001100-00000001-00000010-00000011
    C'est possible de seulement "lire les données de la RAM" (qui contient que des 0 et des 1 donc) ?
    Y'a-t-il moyen avec un BinaryReader ou un MemoryStream par exemple ?
    Merci !

  2. #2
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 170
    Points : 7 422
    Points
    7 422
    Billets dans le blog
    1
    Par défaut
    Oui, en changeant la base au moment de l'affichage :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Convert.ToString(currentByte, 2).PadLeft(8, '0');

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2011
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 81
    Points : 36
    Points
    36
    Par défaut
    Oui mais ici, tu requêtes les bytes en faisant une conversion en int, puis reconvertit en string binaire après pour l'affichage...(c'est pas très optimisé).
    Alors que les données binaire sont déjà présente en mémoire

    idem pour les Convert.ToInt32 ou BitConverter que je souhaite éviter...

  4. #4
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 170
    Points : 7 422
    Points
    7 422
    Billets dans le blog
    1
    Par défaut
    En mémoire, les informations ne sont pas stockées en binaire (base 2), mais en base 256 (un octet).

    Donc non, tu n'as pas des séries "01010" en mémoire, mais des nombres compris entre 0 et 255, exprimés dans une base qu'il est possible de représenter avec une table ASCII étendue (chaque caractère correspond à un chiffre).

    Il faudra donc, de toute façon, convertir ce nombre en base 2, à un moment où à un autre.

    Quand à l'afficher, il faudra le convertir en string, puisque c'est le seul moyen pour afficher quelque chose...

    Ensuite, dans mon exemple, certes, j'utilise une valeur littérale, donc un int.

    Mais Convert(byte, int) existe, donc non, il n'y a pas de convertion en int.
    Ou alors Convert est mal écrit.

  5. #5
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 170
    Points : 7 422
    Points
    7 422
    Billets dans le blog
    1
    Par défaut
    Je viens d'écrire trois autres méthodes pour faire la conversion de byte vers une chaîne représentant la valeur au format binaire.

    D'après mes tests, la version "Test_3" est effectivement 2 à 3 fois plus rapide que l'utilisation de Convert ("Test_1").

    Test_2, même si elle suit la même logique que Test_3, etpourtant relativement optimisée, est bien plus lente (près de 5 à 10 fois plus lente).

    Idem pour Test_4, qui je pensais serait aussi optimisée que Test_3, voir plus et qui s'avère être à peine 2 fois plus rapide que Test_2.

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
     
    using System;
    using System.Diagnostics;
     
    namespace TestBinary
    {
        class Program
        {
            static void Main(string[] args)
            {
                Stopwatch s1;
                Stopwatch s2;
                Stopwatch s3;
                Stopwatch s4;
     
                string res = string.Empty;
     
                for (int k = 0; k < 5; k++)
                {
                    s1 = new Stopwatch();
                    s2 = new Stopwatch();
                    s3 = new Stopwatch();
                    s4 = new Stopwatch();
     
                    s1.Start();
                    for (int i = 0; i < 10000; i++)
                    {
                        for (byte j = byte.MinValue; j < byte.MaxValue; j++)
                        {
                            res = Test_1(j);
                        }
                    }
                    s1.Stop();
     
                    s2.Start();
                    for (int i = 0; i < 10000; i++)
                    {
                        for (byte j = byte.MinValue; j < byte.MaxValue; j++)
                        {
                            res = Test_2(j);
                        }
                    }
                    s2.Stop();
     
                    s3.Start();
                    for (int i = 0; i < 10000; i++)
                    {
                        for (byte j = byte.MinValue; j < byte.MaxValue; j++)
                        {
                            res = Test_3(j);
                        }
                    }
                    s3.Stop();
     
                    s4.Start();
                    for (int i = 0; i < 10000; i++)
                    {
                        for (byte j = byte.MinValue; j < byte.MaxValue; j++)
                        {
                            res = Test_4(j);
                        }
                    }
                    s4.Stop();
     
                    Console.WriteLine("Méthode 1 : {0}", s1.ElapsedMilliseconds);
                    Console.WriteLine("Méthode 2 : {0}", s2.ElapsedMilliseconds);
                    Console.WriteLine("Méthode 3 : {0}", s3.ElapsedMilliseconds);
                    Console.WriteLine("Méthode 4 : {0}", s4.ElapsedMilliseconds);
                }
                Console.ReadKey(true);
            }
     
            static string Test_1(byte val)
            {
                return Convert.ToString(val, 2).PadLeft(8, '0');
            }
     
            static string Test_2(byte val)
            {
                return string.Format("{0}{1}{2}{3}{4}{5}{6}{7}", (val & 128) >> 7, (val & 64) >> 6, (val & 32) >> 5, (val & 16) >> 4, (val & 8) >> 3, (val & 4) >> 2, (val & 2) >> 1, val & 1);
            }
     
            static string Test_3(byte val)
            {
                return new string(new char[8] { (char)('0' + ((val & 128) >> 7)), (char)('0' + ((val & 64) >> 6)), (char)('0' + ((val & 32) >> 5)), (char)('0' + ((val & 16) >> 4)), (char)('0' + ((val & 8) >> 3)), (char)('0' + ((val & 4) >> 2)), (char)('0' + ((val & 2) >> 1)), (char)('0' + (val & 1)) });
            }
     
            static string Test_4(byte val)
            {
                char[] res = new char[8] { '0', '0', '0', '0', '0', '0', '0', '0' };
     
                res[0] += (char)(val & 1);
                res[1] += (char)((val & 2) >> 1);
                res[2] += (char)((val & 4) >> 2);
                res[3] += (char)((val & 8) >> 3);
                res[4] += (char)((val & 16) >> 4);
                res[5] += (char)((val & 32) >> 5);
                res[6] += (char)((val & 64) >> 6);
                res[7] += (char)((val & 128) >> 7);
                return new string(res);
            }
        }
    }

    Si quelqu'un a une version plus optimisée en tête, qu'il se manifeste

    Méthode 1 : 858
    Méthode 2 : 6077
    Méthode 3 : 281
    Méthode 4 : 2943
    Méthode 1 : 831
    Méthode 2 : 5372
    Méthode 3 : 252
    Méthode 4 : 2907
    Méthode 1 : 826
    Méthode 2 : 5402
    Méthode 3 : 261
    Méthode 4 : 2919
    Méthode 1 : 815
    Méthode 2 : 5421
    Méthode 3 : 258
    Méthode 4 : 2923
    Méthode 1 : 814
    Méthode 2 : 5393
    Méthode 3 : 256
    Méthode 4 : 2899
    Voilà...

    Enfin, à mon avis, Convert est amplement suffisant. Et son intérêt c'est que le jour ou tu veux afficher en binaire un nombre suppérieur à 256 (donc autre chose qu'un byte), tu le peux, alors qu'avec mes méthodes, je suis parti du principe que c'était un byte sinon rien entrée.

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2011
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 81
    Points : 36
    Points
    36
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    En mémoire, les informations ne sont pas stockées en binaire (base 2), mais en base 256 (un octet).
    Selon Wikipédia :
    L’octet est une unité de mesure en informatique mesurant la quantité de données. Un octet est lui-même composé de 8 bits, soit 8 chiffres binaires.
    On est d'accord, sur la mémoire RAM, il n'y a que des octets. Mais ces derniers sont physiquement représentés par des 0 ou des 1.
    Moi, je veux juste lire ces 8 chiffres binaires...

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2011
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 81
    Points : 36
    Points
    36
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    Si quelqu'un a une version plus optimisée en tête, qu'il se manifeste .
    Un boucle for est assez couteux en instruction machine. Dans un cas comme celui ci, tu gagnes en performance si tu écris directement tes 8 calcules comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    int compteur = 0;
    byte[] myArrayByte = new byte[] { 0xAA, 0xBB, 0xCC, 0x01, 0x02, 0x03 };
    foreach (int mybyte in myArrayByte )
    {
        binary[compteur + 0] = (char)(((mybyte >> 7) & 0x1) + 48);
        binary[compteur + 1] = (char)(((mybyte >> 6) & 0x1) + 48);
        binary[compteur + 2] = (char)(((mybyte >> 5) & 0x1) + 48);
        binary[compteur + 3] = (char)(((mybyte >> 4) & 0x1) + 48);
        binary[compteur + 4] = (char)(((mybyte >> 3) & 0x1) + 48);
        binary[compteur + 5] = (char)(((mybyte >> 2) & 0x1) + 48);
        binary[compteur + 6] = (char)(((mybyte >> 1) & 0x1) + 48);
        binary[compteur + 7] = (char)(((mybyte >> 0) & 0x1) + 48);
        compteur += 8;
    }

  8. #8
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 170
    Points : 7 422
    Points
    7 422
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par BobbyWeb Voir le message
    Selon Wikipédia :
    On est d'accord, sur la mémoire RAM, il n'y a que des octets. Mais ces derniers sont physiquement représentés par des 0 ou des 1.
    Moi, je veux juste lire ces 8 chiffres binaires...
    Qui n'existent pas.

    Autant physiquement, une carte mémoire, c'est bien constitué de série de 0 et 1 (quoique, ce n'est même pas sûr, et rien n'y oblige), autant le bus mémoire, déjà, il communique en 128 ou 256 bits avec le chipset, j'ai pas suivi l'évolution, et non 8 bits (et encore mois bit à bit, sinon on n'aura pas fini). Idem, maintenant les processeurs sont 64 bits.
    Donc déjà, pour lire un seul octet, tu perds du temps, car matériellement c'est prévu pour en lire plusieurs à la fois, tu dois donc contraindre ton processeur et ton bus mémoire à travailler en mode dégradé... mais alors lire bit à bit, bah c'est juste pas possible, car c'est pas prévu pour. La plus petite unité utilisable en informatique, c'est l'octet, c'est à dire 8 bits à la fois.
    Si tu veux donc convertir un octet en base 2, il faut forcer l'ordinateur à faire des calculs "complexes". Même en assembleur, le plus bas niveau qui existe au niveau programmatique, tu n'as pas accès aux données en binaire.

  9. #9
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 170
    Points : 7 422
    Points
    7 422
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par BobbyWeb Voir le message
    Un boucle for est assez couteux en instruction machine. Dans un cas comme celui ci, tu gagnes en performance si tu écris directement tes 8 calcules comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    int compteur = 0;
    byte[] myArrayByte = new byte[] { 0xAA, 0xBB, 0xCC, 0x01, 0x02, 0x03 };
    foreach (int mybyte in myArrayByte )
    {
        binary[compteur + 0] = (char)(((mybyte >> 7) & 0x1) + 48);
        binary[compteur + 1] = (char)(((mybyte >> 6) & 0x1) + 48);
        binary[compteur + 2] = (char)(((mybyte >> 5) & 0x1) + 48);
        binary[compteur + 3] = (char)(((mybyte >> 4) & 0x1) + 48);
        binary[compteur + 4] = (char)(((mybyte >> 3) & 0x1) + 48);
        binary[compteur + 5] = (char)(((mybyte >> 2) & 0x1) + 48);
        binary[compteur + 6] = (char)(((mybyte >> 1) & 0x1) + 48);
        binary[compteur + 7] = (char)(((mybyte >> 0) & 0x1) + 48);
        compteur += 8;
    }
    T'as pas dû bien lire mon code alors, parce que dans aucune de mes 4 méthodes je n'ai de boucle. Les boucles sont là pour faire le benchmark des méthodes.
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
            static string Test_1(byte val)
            {
                return Convert.ToString(val, 2).PadLeft(8, '0');
            }
     
            static string Test_2(byte val)
            {
                return string.Format("{0}{1}{2}{3}{4}{5}{6}{7}", (val & 128) >> 7, (val & 64) >> 6, (val & 32) >> 5, (val & 16) >> 4, (val & 8) >> 3, (val & 4) >> 2, (val & 2) >> 1, val & 1);
            }
     
            static string Test_3(byte val)
            {
                return new string(new char[8] { (char)('0' + ((val & 128) >> 7)), (char)('0' + ((val & 64) >> 6)), (char)('0' + ((val & 32) >> 5)), (char)('0' + ((val & 16) >> 4)), (char)('0' + ((val & 8) >> 3)), (char)('0' + ((val & 4) >> 2)), (char)('0' + ((val & 2) >> 1)), (char)('0' + (val & 1)) });
            }
     
            static string Test_4(byte val)
            {
                char[] res = new char[8] { '0', '0', '0', '0', '0', '0', '0', '0' };
     
                res[0] += (char)(val & 1);
                res[1] += (char)((val & 2) >> 1);
                res[2] += (char)((val & 4) >> 2);
                res[3] += (char)((val & 8) >> 3);
                res[4] += (char)((val & 16) >> 4);
                res[5] += (char)((val & 32) >> 5);
                res[6] += (char)((val & 64) >> 6);
                res[7] += (char)((val & 128) >> 7);
                return new string(res);
            }

    Test_3 étant la plus optimisée (bien plus que ton code, qui ressemble à ma méthode 4, qui est très lente, bien plus lente que le Convert)

  10. #10
    Rédacteur
    Avatar de Nathanael Marchand
    Homme Profil pro
    Expert .Net So@t
    Inscrit en
    Octobre 2008
    Messages
    3 615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Expert .Net So@t
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Points : 8 082
    Points
    8 082
    Par défaut
    En effet, les processeurs ne sont pas capables de travailler avec plus petit que l'octet! D'ailleurs, un booléen occupe un octet. (C'est pour ca qu'on utilise des flags et des opérations bits à bits pour éviter de perdre les 7bits restants. Pour s'en convaincre un sizeof(bool) retourne 1 et non pas 1/8 (ce qui serait perturbant d'ailleurs ).

  11. #11
    Expert confirmé
    Inscrit en
    Avril 2008
    Messages
    2 564
    Détails du profil
    Informations personnelles :
    Âge : 64

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 564
    Points : 4 442
    Points
    4 442
    Par défaut
    bonjour BobbyWeb
    On ne voit pas la finalite de telles questions.....
    Pour preuve ton code :tu peux shifter,roller tes bits ,xorer tes bits .
    Ces operations ont ete cree en programmation assembleur au debut de la technique informatique(il n y avait ni le c,ni le c# ni le vb.net .....) pour acceder au contenu de l'octet et le manipuler bit à bit....

    Tout simplement si tu veux ,pour rejoindre ce qu'as dit Stringbuilder et Nathanael Marchand,mais en d'autres termes plus clair l'octet est l'unite standard de mesure des donnees en memoire comme l'etalon du metre
    Dès le 19 mars 1791 le mètre, base du nouveau système métrique, était théoriquement défini comme égal à la dix millionième partie du quart du méridien terrestre, encore fallait-il établir dans la pratique la longueur de ce dernier.
    En 1795, un nouveau mètre-étalon en platine, dédié " à tous les temps, à tous les peuples ", ne soit déposé en 1799, aux archives de la république.
    .
    A Sevres pres de Paris precisemment......

    Bien sur des excentriques comme Mabrouki ou BobbyWeb peuvent vouloir ,mais libre à eux - utiliser le cm,le mm ou le km oh pardon .....le bit ,le demi-octet...ou le mot (Word qui contient 2 octet) ou la ¨Page(64 kilo-octets).
    En assembleur tu peux charger ou decharger un demi-octet dans un registre CPU...mais adresser seulement un octet en memoire(y acceder).... et egalement roller les bits,les shifter à droite ou a gauche etc ....comme en c# ou vb.net...

    Quant à l'affirmation selon laquelle les "bits" n'existe pas en memoire , c'est abuser de la richesse de la langue francaise et de l'informatique ....il sufit qu'on accede (roller,shifter des bits etc...) meme -indirectement à une donnee (le bit) et qu'on puisse la quantifier avec precision (le bit dans notre cas)-pour dire scientifiquement qu"elle existe....comme le cm puisqu"on sait le definir donc l'utiliser.....

    Tu es dans ce que j'appelle , une discussion à la Mr Jourdain ,tu accedes aux bits ,tu t'amuses avec presque et tu engage une discussion pour savoir comment acceder "directement" aux bits ...
    Cette question ne peut avoir qu' un seul sens : aller à Sevre,enlever le "metre-etalon" en platine et le substituer par le "cm etalon"..........ou aller à la Silicon Valley reformer les machines qui utilisent "l'octet etalon" et les remplacer par des machines qui utilisent le "bit etalon".......

    Ce qui n'est pas tres positif.........
    bon code....

Discussions similaires

  1. [AC-2007] Soft pour lire les données binaires
    Par Tristan33000 dans le forum Access
    Réponses: 1
    Dernier message: 29/04/2013, 13h39
  2. Problème pour lire les donnée d'une table externe
    Par mardoch dans le forum SQL*Loader
    Réponses: 6
    Dernier message: 17/07/2008, 16h41
  3. [VB+Lotus Notes] Lire les données d'une DB Lotus
    Par kenn dans le forum VB 6 et antérieur
    Réponses: 4
    Dernier message: 25/08/2005, 15h21
  4. Problème avec les données binaire
    Par Lachessis dans le forum VB 6 et antérieur
    Réponses: 5
    Dernier message: 10/08/2005, 17h38
  5. [CR] lire les données de gauche a droite
    Par speed034 dans le forum SAP Crystal Reports
    Réponses: 1
    Dernier message: 14/10/2004, 18h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo