2010-08-12 8 views
4

J'essaie de charger des valeurs décimales à partir d'un fichier, mais je ne peux pas trouver la bonne façon de prendre les valeurs brutes et de les convertir en nombres décimaux.Comment convertir des valeurs d'octets en nombres décimaux?

J'ai lu le fichier dans un tableau d'octets, et chaque segment de quatre octets est censé représenter une valeur décimale. Pour aider à comprendre, j'ai construit une table de la façon dont les valeurs décimales 1 à 46 sont représentés en morceaux de quatre octets.

Par exemple, le nombre 1 apparaît comme 0,0128,63 le nombre 2 comme 0,0,0,64 et ainsi de suite jusqu'à 46, qui est 0,0,56,66. La table complète est disponible here.

Il existe également une autre série de nombres qui vont à trois décimales et incluent les négatifs, à savoir here.

La seule documentation J'ai états

Ils sont stockés octet le moins significatif: la première de 1, 256, de 65536, de 16.777.216 de. La séquence hexadécimale 01 01 00 00 devient alors le nombre 257 (décimal). En C/C++, lire par ex. un flotteur, faire: float x; fread (& x, sizeof (flottant), 1, fichierptr);

Cependant, j'utilise la méthode File.ReadAllBytes de .NET, ce qui n'est pas très utile. Si quelqu'un peut prendre quelques minutes pour regarder les fichiers d'exemples et voir s'ils peuvent trouver un moyen de convertir les valeurs en décimales, je serais très reconnaissant.

Répondre

3

Vous pouvez utiliser BitConverter.ToSingle pour lire une valeur flottante à partir d'un tableau d'octets, afin d'obtenir une séquence de flotteurs , vous pouvez faire quelque chose comme ceci:

byte[] data = File.ReadAllBytes(fileName); 
int count = data.Length/4; 
Debug.Assert(data.Length % 4 == 0); 

IEnumerable<float> values = Enumerable.Range(0, count) 
    .Select(i => BitConverter.ToSingle(data, i*4)); 
+0

Je l'ai marqué correctement car il est légèrement plus détaillé. Merci beaucoup, ne m'attendais pas à être aussi simple. – gilles27

2

Avez-vous envisagé d'utiliser la classe BitConverter? Il convertit entre les tableaux d'octets et divers types.

Edit: MSDN a un commentaire utile sur la documentation BitConverter à http://msdn.microsoft.com/en-us/library/system.bitconverter_methods(v=vs.85).aspx:

public static decimal ToDecimal(byte[] bytes) 
{ 
    int[] bits = new int[4]; 
    bits[0] = ((bytes[0] | (bytes[1] << 8)) | (bytes[2] << 0x10)) | (bytes[3] << 0x18); //lo 
    bits[1] = ((bytes[4] | (bytes[5] << 8)) | (bytes[6] << 0x10)) | (bytes[7] << 0x18); //mid 
    bits[2] = ((bytes[8] | (bytes[9] << 8)) | (bytes[10] << 0x10)) | (bytes[11] << 0x18); //hi 
    bits[3] = ((bytes[12] | (bytes[13] << 8)) | (bytes[14] << 0x10)) | (bytes[15] << 0x18); //flags 

    return new decimal(bits); 
} 

public static byte[] GetBytes(decimal d) 
{ 
    byte[] bytes = new byte[16]; 

    int[] bits = decimal.GetBits(d); 
    int lo = bits[0]; 
    int mid = bits[1]; 
    int hi = bits[2]; 
    int flags = bits[3]; 

    bytes[0] = (byte)lo; 
    bytes[1] = (byte)(lo >> 8); 
    bytes[2] = (byte)(lo >> 0x10); 
    bytes[3] = (byte)(lo >> 0x18); 
    bytes[4] = (byte)mid; 
    bytes[5] = (byte)(mid >> 8); 
    bytes[6] = (byte)(mid >> 0x10); 
    bytes[7] = (byte)(mid >> 0x18); 
    bytes[8] = (byte)hi; 
    bytes[9] = (byte)(hi >> 8); 
    bytes[10] = (byte)(hi >> 0x10); 
    bytes[11] = (byte)(hi >> 0x18); 
    bytes[12] = (byte)flags; 
    bytes[13] = (byte)(flags >> 8); 
    bytes[14] = (byte)(flags >> 0x10); 
    bytes[15] = (byte)(flags >> 0x18); 

    return bytes; 
} 
+0

Merci c'est définitivement le chemin à parcourir. – gilles27

+0

Malheureusement, il n'implémente pas la conversion décimale. –

+0

@EranBetzalel MSDN a du code pour implémenter les membres "manquants" de BitConverter. Voir ma mise à jour éditée. – BlueMonkMN

0

comme d'autres l'ont mentionné, utilisez la classe BitConverter, voir l'exemple ci-dessous:

 byte[] bytez = new byte[] { 0x00, 0x00, 0x80, 0x3F }; 
    float flt = BitConverter.ToSingle(bytez, 0); // 1.0 

    bytez = new byte[] { 0x00, 0x00, 0x00, 0x40 }; 
    flt = BitConverter.ToSingle(bytez, 0); // 2.0 

    bytez = new byte[] { 0, 0, 192, 190 }; 
    flt = BitConverter.ToSingle(bytez, 0); // -0.375 
0

La bibliothèque .NET a implémenté la méthode Decimal.GetBytes() en interne.

Je l'ai utilisé la bibliothèque .NET décompilé pour créer une des méthodes simples de conversion entre décimal et octet arrary - vous pouvez le trouver ici:

https://gist.github.com/eranbetzalel/5384006#file-decimalbytesconvertor-cs

EDIT: Voici le code source complet de mon lien.

public decimal BytesToDecimal(byte[] buffer, int offset = 0) 
{ 
    var decimalBits = new int[4]; 

    decimalBits[0] = buffer[offset + 0] | (buffer[offset + 1] << 8) | (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24); 
    decimalBits[1] = buffer[offset + 4] | (buffer[offset + 5] << 8) | (buffer[offset + 6] << 16) | (buffer[offset + 7] << 24); 
    decimalBits[2] = buffer[offset + 8] | (buffer[offset + 9] << 8) | (buffer[offset + 10] << 16) | (buffer[offset + 11] << 24); 
    decimalBits[3] = buffer[offset + 12] | (buffer[offset + 13] << 8) | (buffer[offset + 14] << 16) | (buffer[offset + 15] << 24); 

    return new Decimal(decimalBits); 
} 

public byte[] DecimalToBytes(decimal number) 
{ 
    var decimalBuffer = new byte[16]; 

    var decimalBits = Decimal.GetBits(number); 

    var lo = decimalBits.Value[0]; 
    var mid = decimalBits.Value[1]; 
    var hi = decimalBits.Value[2]; 
    var flags = decimalBits.Value[3]; 

    decimalBuffer[0] = (byte)lo; 
    decimalBuffer[1] = (byte)(lo >> 8); 
    decimalBuffer[2] = (byte)(lo >> 16); 
    decimalBuffer[3] = (byte)(lo >> 24); 

    decimalBuffer[4] = (byte)mid; 
    decimalBuffer[5] = (byte)(mid >> 8); 
    decimalBuffer[6] = (byte)(mid >> 16); 
    decimalBuffer[7] = (byte)(mid >> 24); 

    decimalBuffer[8] = (byte)hi; 
    decimalBuffer[9] = (byte)(hi >> 8); 
    decimalBuffer[10] = (byte)(hi >> 16); 
    decimalBuffer[11] = (byte)(hi >> 24); 

    decimalBuffer[12] = (byte)flags; 
    decimalBuffer[13] = (byte)(flags >> 8); 
    decimalBuffer[14] = (byte)(flags >> 16); 
    decimalBuffer[15] = (byte)(flags >> 24); 

    return decimalBuffer; 
} 
Questions connexes