Convert System.Decimal to and from Byte Arrays (VB & C#)

Convert System.Decimal to and from Byte Arrays (VB & C#)



Introduction

At first glance converting the datatype (System.Decimal) to and from bytes may appear to be a challenge, this is because the BitConverter and Convert classes do not have methods to convert decimals to and from bytes with. The decimal data type has built in methods for converting, although they are somewhat obscure. Here are two simple functions for converting decimals to a list of bytes, and then back to a decimal (at the end of the article).

Getting the bytes of a System.Decimal

You may have noticed or not, but the Decimal class has a shared method called "GetBits". This method will return an array containing four 32 bit integers, so not quite the bits you would be expecting. So at first you might be expecting those four integers to be one's or zero's. This is not the case. The bits of the decimal are actually extrapolated by taking the bytes of those four 32 bit integers (4*32=128). This means that a decimal is a 128 bit (16 bytes) structure.

Creating an instance of the System.Decimal from bytes

So you may have been in a place where you were pulling your hair out trying to figure out how to get an instance of System.Decimal from those bytes. This is because you may be used to creating instances of numeric datatypes using the BitConverter class or the Convert class. The BitConverter & Convert classes do not have any methods built in to support the Decimal datatype. So this may seem like a really confusing problem at first, but the truth is that the Decimal class has a constructor that accepts an array of exactly four 32 bit integers as a parameter.

Summary

So in a nutshell, this means that you can take your binary information using the Decimal.GetBits function, save it to your file, or whatever you need to do. You can later then load those bytes into an array, convert those bytes into integers, put those integers into another array, and finally, pass that array of integers to the decimal's constructor sub.

Code Examples

Visual Basic
'Prevent simple errors with options
Option Strict On
Option Explicit On
Option Infer Off
Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        'create a decimal for testing
        Dim testDecimal As Decimal = 987.123456D
        'Get the bytes of the decimal
        Dim decimalBytes As Byte() = BitconverterExt.GetBytes(testDecimal)
        'Create a decimal from those bytes
        Dim fromBytes As Decimal = BitconverterExt.ToDecimal(decimalBytes)
        'Display the result
        MsgBox(fromBytes.ToString)
    End Sub
End Class
Public Class BitconverterExt
    Public Shared Function GetBytes(dec As Decimal) As Byte()
        'Load four 32 bit integers from the Decimal.GetBits function
        Dim bits As Int32() = Decimal.GetBits(dec)
        'Create a temporary list to hold the bytes
        Dim bytes As New List(Of Byte)
        'iterate each 32 bit integer
        For Each i As Int32 In bits
            'add the bytes of the current 32bit integer
            'to the bytes list
            bytes.AddRange(BitConverter.GetBytes(i))
        Next
        'return the bytes list as an array
        Return bytes.ToArray
    End Function
    Public Shared Function ToDecimal(bytes As Byte()) As Decimal
        'check that it is even possible to convert the array
        If bytes.Count <> 16 Then Throw New Exception("A decimal must be created from exactly 16 bytes")
        'make an array to convert back to int32's
        Dim bits(3) As Int32
        For i As Integer = 0 To 15 Step 4
            'convert every 4 bytes into an int32
            bits(i \ 4) = BitConverter.ToInt32(bytes, i)
        Next
        'Use the decimal's new constructor to
        'create an instance of decimal
        Return New Decimal(bits)
    End Function
End Class

C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e){}
        private void button1_Click(object sender, EventArgs e)
        {
            //create a decimal for testing
            decimal testDecimal = 987.123456m;
            //Get the bytes of the decimal
            byte[] decimalBytes = BitconverterExt.GetBytes(testDecimal);
            //Create a decimal from those bytes
            decimal fromBytes = BitconverterExt.ToDecimal(decimalBytes);
            //Display the result
           MessageBox .Show(fromBytes.ToString());
        }
    }
    public class BitconverterExt
    {
           public static byte[] GetBytes(decimal dec)
        {
            //Load four 32 bit integers from the Decimal.GetBits function
            Int32[] bits = decimal.GetBits(dec);
            //Create a temporary list to hold the bytes
            List<byte> bytes = new List<byte>();
            //iterate each 32 bit integer
            foreach (Int32 i in bits)
            {
                //add the bytes of the current 32bit integer
                //to the bytes list
                bytes.AddRange(BitConverter.GetBytes(i));
            }
            //return the bytes list as an array
            return bytes.ToArray();
        }
        public static decimal ToDecimal(byte[] bytes)
        {
            //check that it is even possible to convert the array
            if (bytes.Count() != 16)
                throw new Exception("A decimal must be created from exactly 16 bytes");
            //make an array to convert back to int32's
            Int32[] bits = new Int32[4];
            for (int i = 0; i <= 15; i += 4)
            {
                //convert every 4 bytes into an int32
                bits[i/4] = BitConverter.ToInt32(bytes, i);
            }
            //Use the decimal's new constructor to
            //create an instance of decimal
            return new decimal(bits);
        }
    }
}



References

I hope you find this helpful!
Top Way To Track Webpages
Adding Stats 

Leave a Comment
  • Please add 2 and 2 and type the answer here:
  • Post
Wiki - Revision Comment List(Revision Comment)
Sort by: Published Date | Most Recent | Most Useful
Comments
  • Richard Mueller edited Revision 10. Comment: Removed tags "visual" and "studio" (I don't see where they add value), added tag "Visual Studio".

  • Balaji M Kundalam edited Revision 6. Comment: Typography - minor edit

  • Maheshkumar S Tiwari edited Revision 5. Comment: Added Tags and formatting

  • Maheshkumar S Tiwari edited Revision 4. Comment: Added TOC and formatting

  • Paul Ishak edited Revision 1. Comment: add hit counter, sample project link to msdn galleries

Page 1 of 1 (5 items)
Wikis - Comment List
Sort by: Published Date | Most Recent | Most Useful
Posting comments is temporarily disabled until 10:00am PST on Saturday, December 14th. Thank you for your patience.
Comments
  • Paul Ishak edited Revision 1. Comment: add hit counter, sample project link to msdn galleries

  • Maheshkumar S Tiwari edited Revision 4. Comment: Added TOC and formatting

  • Maheshkumar S Tiwari edited Revision 5. Comment: Added Tags and formatting

  • Balaji M Kundalam edited Revision 6. Comment: Typography - minor edit

  • Richard Mueller edited Revision 10. Comment: Removed tags "visual" and "studio" (I don't see where they add value), added tag "Visual Studio".

Page 1 of 1 (5 items)