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).
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.
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.
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.
'Prevent simple errors with options
Option
Strict
On
Explicit
Infer Off
Public
Class
Form1
Private
Sub
Button1_Click(sender
As
Object
, e
EventArgs)
Handles
Button1.Click
'create a decimal for testing
Dim
testDecimal
Decimal
= 987.123456D
'Get the bytes of the decimal
decimalBytes
Byte
() = BitconverterExt.GetBytes(testDecimal)
'Create a decimal from those bytes
fromBytes
= BitconverterExt.ToDecimal(decimalBytes)
'Display the result
MsgBox(fromBytes.ToString)
End
BitconverterExt
Shared
Function
GetBytes(dec
)
()
'Load four 32 bit integers from the Decimal.GetBits function
bits
Int32() =
.GetBits(dec)
'Create a temporary list to hold the bytes
bytes
New
List(Of
'iterate each 32 bit integer
For
Each
i
Int32
In
'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
ToDecimal(bytes
())
'check that it is even possible to convert the array
If
bytes.Count <> 16
Then
Throw
Exception(
"A decimal must be created from exactly 16 bytes"
'make an array to convert back to int32's
bits(3)
Integer
= 0
To
15
Step
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
(bits)
using
System;
System.Collections.Generic;
System.ComponentModel;
System.Data;
System.Drawing;
System.Linq;
System.Text;
System.Threading.Tasks;
System.Windows.Forms;
namespace
WindowsFormsApplication1
{
public
partial
class
Form1 : Form
Form1()
InitializeComponent();
}
private
void
Form1_Load(
object
sender, EventArgs e){}
button1_Click(
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
fromBytes = BitconverterExt.ToDecimal(decimalBytes);
//Display the result
MessageBox .Show(fromBytes.ToString());
static
[] GetBytes(
dec)
//Load four 32 bit integers from the Decimal.GetBits function
Int32[] bits =
.GetBits(dec);
//Create a temporary list to hold the bytes
List<
> bytes =
new
>();
//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();
ToDecimal(
[] bytes)
//check that it is even possible to convert the array
if
(bytes.Count() != 16)
throw
);
//make an array to convert back to int32's
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
(bits);
I hope you find this helpful! Adding Stats
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".