Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / New Users / March 2006

Tip: Looking for answers? Try searching our database.

Converting to big -endian

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Kenny - 16 Mar 2006 22:30 GMT
Hello All - have a problem that I'm pulling my hair out on. I'm trying to
take a hex value and convert it to 16bit big-endian format. I can eaisly get
it to little-endian format by convert.ToUInt16(&H600) - works like a champ.
But there is no conver to UInt16 big-endian. Am I missing a conversion
function somewhere or do I have to do some shifting and bitmasking to make
this work?
Nick Hounsome - 17 Mar 2006 09:57 GMT
> Hello All - have a problem that I'm pulling my hair out on. I'm trying to
> take a hex value and convert it to 16bit big-endian format. I can eaisly
[quoted text clipped - 4 lines]
> function somewhere or do I have to do some shifting and bitmasking to make
> this work?

Any routine that converts endianness converts it both ways since it is just
a byte swap so you can use the same method for both.

The "proper" way to do endianness is to have machine specific methods that
either swap or don't depending on the architecture of the machine on which
they are running - In this scenario you don't have to know your architecture
or even think - you just call the method corresponding to the
incoming/outgoing order on all values as they enter and leave your app.

e.g.  If my external interface is defined as BigEndian I write

internalVal = BigEndian(externalVal); // incoming
externalVal = BigEndian(internalVal); // outgoing

and if little endian i write:

internalVal = LittleEndian(externalVal); // incoming
externalVal = LittleEndian(internalVal); // outgoing

For any given architecture one of these methods will do nothing and the
other will swap bytes but I don't have to know or care which it is which.

As far as I know no major system does it this way but I came across it as
macros in QNX/Momentics when I was writing embedded C++ and it certainly
makes life much simpler. Of course as macros there is no cost in the no-op
method which is not the case with C#. You could have the same effect by
using something like:

[Conditional("BigEndian")]
void LittleEndian(ref int i) { i = Swap(i); }

[Conditional("LittleEndian")]
void BigEndian(ref int i) { i = Swap(i); }

Of course I appreciate that all the readers of this thread are so embedded
in the MS/intel world that this is a non-issue but personally I keep
forgetting and I like the elegance of this approach.
Kevin Spencer - 17 Mar 2006 13:07 GMT
Create a byte array of the same size as the original value. Read the bytes
in the original value into the array in reverse order. Use the BitConverter
class to convert the byte array to the return type. Piece of cake.

Signature

HTH,

Kevin Spencer
Microsoft MVP
.Net Developer

Presuming that God is "only an idea" -
Ideas exist.
Therefore, God exists.

> Hello All - have a problem that I'm pulling my hair out on. I'm trying to
> take a hex value and convert it to 16bit big-endian format. I can eaisly
[quoted text clipped - 4 lines]
> function somewhere or do I have to do some shifting and bitmasking to make
> this work?
Kenny - 17 Mar 2006 15:35 GMT
Tried that and it doesnt work... Problem is that bitconvert .ToUInt16
converts back to little-endian. I need to basically mimick the PERL pack
function... If I do this in PERL - $header = pack("n", 0xD0CF);  I get d0 cf  
if I $header = pack("v", 0xD0CF); I get cf d0 - in .net if I
convert.tou16int(&HD0CF) I get as expected cf d0 - but  every different
conversion to big-endian I try I get reults like 35 0 34 0 36 ....

> Create a byte array of the same size as the original value. Read the bytes
> in the original value into the array in reverse order. Use the BitConverter
[quoted text clipped - 8 lines]
> > function somewhere or do I have to do some shifting and bitmasking to make
> > this work?
Nick Hounsome - 17 Mar 2006 17:25 GMT
There seems to be some misunderstanding going on.

1. BitConverter.ToUInt16 takes a byte array and an index not an int (hex or
otherwise)
2. Convert.ToUint16 only does extension and signed/unsigned conversion.
3. The fact that the input value to any method is  hexadecimal constant is
irrelevant.

IPAddress.HostToNetworkOrder(Int16 val) will do the byte swapping for you on
a little endian machine (i.e. intel)
and you an either use (unchecked) casts or the full ugliness of

Convert.ToUInt16( IPAddress.HostToNetworkOrder( Convert.ToInt16(
myUInt ) ) );

It seems to me that the BitConverter methods should be instance methods not
static and there should be an instance for big endian and an instance for
little endian.

> Tried that and it doesnt work... Problem is that bitconvert .ToUInt16
> converts back to little-endian. I need to basically mimick the PERL pack
[quoted text clipped - 21 lines]
>> > make
>> > this work?
Kenny - 17 Mar 2006 18:15 GMT
Nick.. yes you are correct... and thanks for the input.. I kept getting
convert.touint16 confused with bitconverter.touint16.. sublte distinction
that can get overlooked.. I actually took Kevin's advice and put into an
array an looped backwards then use the bitocnverter with the proper index.
This whole process is so annoying all for a customer who wants a data file
with one particular column in big-endian order.. why I have no idea...  any
way here is what I did to make it work. .any suggestions for makign better?

Dim foo As Byte() = BitConverter.GetBytes(&H1AE1)
       Dim bar() As Byte = New Byte((foo.Length - 1)) {}

       Dim i As Integer = 0
       Dim u As Integer = 0
       For i = foo.Length - 1 To 0 Step -1
           bar(u) = foo(i)
           u += 1
       Next

BitConverter.ToUInt16(bar, 2)

this will mimick perl... pack("n",0x1AE1)

Kevin Spencer.. r u the same Kevin Spencer from takempis.com? If so remember
me I was one of your MVP a long time ago.. how have you been?

> There seems to be some misunderstanding going on.
>
[quoted text clipped - 40 lines]
> >> > make
> >> > this work?
Kevin Spencer - 17 Mar 2006 19:50 GMT
Hi Kenny,

Your code looks pretty good.

Yes, I'm the same guy, but it's been a long time, so I can't say
specifically that I remember you. Still, it's good to hear from you again!

Signature

Kevin Spencer
Microsoft MVP
.Net Developer

Presuming that God is "only an idea" -
Ideas exist.
Therefore, God exists.

> Nick.. yes you are correct... and thanks for the input.. I kept getting
> convert.touint16 confused with bitconverter.touint16.. sublte distinction
[quoted text clipped - 77 lines]
>> >> > make
>> >> > this work?
Nick Hounsome - 18 Mar 2006 09:38 GMT
But this is much slower than bit shuffling with HostToNetworkOrder or just
doing it yourself.

Why would you bother splitting it into a byte array first?

Even if it is already in a byte array it is simpler code to just convert it
and then use HostToNetworkOrder to shufle the bits.

> Nick.. yes you are correct... and thanks for the input.. I kept getting
> convert.touint16 confused with bitconverter.touint16.. sublte distinction
[quoted text clipped - 77 lines]
>> >> > make
>> >> > this work?
Kevin Spencer - 18 Mar 2006 14:06 GMT
Hi Nick,

> But this is much slower than bit shuffling with HostToNetworkOrder or just
> doing it yourself.

I suppose it all depends on what you're doing. If you're working with a
UInt16 in the first place, maybe. I'm not entirely sure that using
HostToNetworkOrder is more efficient otherwise. It may simply be doing what
you're talking about. After all, the bytes *do* have to be reversed. So, in
your case, you're adding the step of converting the bytes to a UInt16 and
then calling a function which converts the UInt16 to an array of bytes,
reverses the order, and then converts the array of bytes back to a number. I
suppose it is possible that it does it all in an unmanaged bitwise way under
the hood, but I doubt it.

In addition, this is fine and dandy if the data you're working with is
confined to 16, 32, or 64-bit numbers. Otherwise, you will have to roll your
own method, as I've done in my library, which works with a large variety of
data types, for the purpose of reading TIFF files.

Signature

HTH,

Kevin Spencer
Microsoft MVP
.Net Developer

Presuming that God is "only an idea" -
Ideas exist.
Therefore, God exists.

> But this is much slower than bit shuffling with HostToNetworkOrder or just
> doing it yourself.
[quoted text clipped - 90 lines]
>>> >> > make
>>> >> > this work?
Kevin Spencer - 17 Mar 2006 19:48 GMT
You lost me, Kenny. I have been using the function I described for quite
awhile without issues. The only difference is that I am reading from a
stream. But I'm reversing the bytes and using a BitConverter to convert them
back. Here's the acutal code I wrote:

/// <summary acc="protected" type="System.UInt16">
/// Overloaded.Reads a <c>System.UInt16</c> value using Big-Endian
/// or Little-Endian byte order.
/// </summary>
/// <param name="reader"><c>System.IO.BinaryReader</c> to read from.</param>
/// <returns><c>System.UInt16</c> value.</returns>
/// <remarks>Reads from the current position of the <paramref
name="reader"/>.</remarks>
protected ushort ReadUInt16(BinaryReader reader)
{
   if (_ByteOrder == ByteOrder.LittleEndian)
   {
       return reader.ReadUInt16();
   }
   else // Big-Endian
   {
       byte[] bytes = new byte[2];
       bytes[1] = reader.ReadByte();
       bytes[0] = reader.ReadByte();
       return BitConverter.ToUInt16(bytes, 0);
   }
}

/// <summary acc="protected" type="System.UInt16">
/// Overloaded.Reads a <c>System.UInt16</c> value using Big-Endian
/// or Little-Endian byte order.
/// </summary>
/// <param name="reader"><c>System.IO.BinaryReader</c> to read from.</param>
/// <param name="Offset">Offset from beginning of file.</param>
/// <returns><c>System.UInt16</c> value.</returns>
protected ushort ReadUInt16(BinaryReader reader, long Offset)
{
   reader.BaseStream.Seek(Offset, SeekOrigin.Begin);
   return ReadUInt16(reader);
}

Signature

HTH,

Kevin Spencer
Microsoft MVP
.Net Developer

Presuming that God is "only an idea" -
Ideas exist.
Therefore, God exists.

> Tried that and it doesnt work... Problem is that bitconvert .ToUInt16
> converts back to little-endian. I need to basically mimick the PERL pack
[quoted text clipped - 21 lines]
>> > make
>> > this work?

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.