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 / Languages / C# / October 2007

Tip: Looking for answers? Try searching our database.

BitConverter.ToInt16 doesn't work correct

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
SushiSean - 14 Oct 2007 20:43 GMT
Hello. I have a problem with getting short value from 2 byte array.
I have this code. There are 2 short values in bytes.

byte[] cast = { 18, 152, 00, 80 };
Int32 port = BitConverter.ToInt16(cast, 0); // -26606 - wrong!
Int32 port2 = BitConverter.ToInt16(cast, 2); // 20480 - wrong!

//port and port2 get not correct values
//and I found solution in google
short result1 = (short)(((short)cast[1]) | (short)(cast[0] * 256)); //4760 -
correct!
short result2 = (short)(((short)cast[3]) | (short)(cast[2] * 256)); //80 -
correct!

why it happends? How make BitConverter work correct?
Peter Duniho - 14 Oct 2007 21:17 GMT
> Hello. I have a problem with getting short value from 2 byte array.
> I have this code. There are 2 short values in bytes.
>
> byte[] cast = { 18, 152, 00, 80 };
> Int32 port = BitConverter.ToInt16(cast, 0); // -26606 - wrong!

-26606 is the correct result.  Your 16-bit number is 0x9812, which when
interpreted as a signed 16-bit integer is in fact -26606.

> Int32 port2 = BitConverter.ToInt16(cast, 2); // 20480 - wrong!

Likewise, 20480 is the correct result.  Your 16-bit number is 0x5000,
which when interpreted as a signed 16-bit integer is in fact 20480.

> //port and port2 get not correct values

It appears to me that you are confused about the native, little-endian
number format used by the Intel hardware running your code, and the
"network order" used in TCP/IP, which is big-endian.

> //and I found solution in google
> short result1 = (short)(((short)cast[1]) | (short)(cast[0] * 256)); //4760 -
> correct!
> short result2 = (short)(((short)cast[3]) | (short)(cast[2] * 256)); //80 -
> correct!

Those are only the correct values if your data is in big-endian format.
 If your data is in big-endian format, it is a mistake to ask
BitConverter, which operates only on little-endian data, to convert it.

> why it happends? How make BitConverter work correct?

Don't lie to it about the data you're passing it.  If you want it to
convert data that you have that starts in big-endian format, you need to
convert that data to little-endian before you pass it to BitConverter by
swapping the bytes so that they are in the correct order.

Pete
SushiSean - 15 Oct 2007 01:19 GMT
> Don't lie to it about the data you're passing it.  If you want it to
> convert data that you have that starts in big-endian format, you need to
> convert that data to little-endian before you pass it to BitConverter

How to make this convert to little-endian?
Peter Duniho - 15 Oct 2007 01:37 GMT
>> Don't lie to it about the data you're passing it.  If you want it to
>> convert data that you have that starts in big-endian format, you need to
>> convert that data to little-endian before you pass it to BitConverter
>
> How to make this convert to little-endian?

It was in my post.  You trimmed out the procedure I described in the
above quote.

Beyond that, if you are going to be using BitConverter, you should
probably learn more about actual data formats, and in this case
especially about byte-order and how to deal with differences in that.
And in particular, you seem to be doing network address work here, where
the byte-ordering for the format is very important, since many network
APIs use big-endian even on computers that are natively little-endian.
.NET translates for you, when you give it plain little-endian integers,
but it's quite common to see network addresses stored as big-endian.

Basically, you should probably take a step back and gain better
familiarity with the byte-ordering issue before you attempt to write
code that is dependent on byte-ordering.

Pete
Kevin Spencer - 15 Oct 2007 11:33 GMT
Here is a  function I wrote that is designed for a BinaryReader:

byte[] ReadBytes(BinaryReader reader, int length, bool littleEndian)
{
   byte[] bytes = new byte[length];
   if (littleEndian)
   return reader.ReadBytes(length);
   else
   {
       for (int i = length - 1; i > -1; i--)
           bytes[i] = reader.ReadByte();
           return bytes;
   }
}

Simply put, when the byte order is Big-Endian, you reverse the order of the
bytes.

Signature

HTH,

Kevin Spencer
Microsoft MVP

DSI PrintManager, Miradyne Component Libraries:
http://www.miradyne.net

>>> Don't lie to it about the data you're passing it.  If you want it to
>>> convert data that you have that starts in big-endian format, you need to
[quoted text clipped - 19 lines]
>
> Pete
Marc Gravell - 15 Oct 2007 11:47 GMT
Note that this will only work if the binary data is a single value
(however many bytes that is for the type in question); if it is a true
stream of successive values you could be in a pickle.

Minor aside; personally I would have called reader.ReadBytes() to fill
the buffer in either case, and then (if littleEndian) reversed the
buffer locally. Horses for courses...

Marc
Michael C - 16 Oct 2007 02:07 GMT
> Here is a  function I wrote that is designed for a BinaryReader:
>
[quoted text clipped - 13 lines]
> Simply put, when the byte order is Big-Endian, you reverse the order of
> the bytes.

Doesn't this reverse the order of the entire array?

Michael
Marc Gravell - 16 Oct 2007 08:51 GMT
from inspection, it appears to - hence my reply; valid in some
circumstances, but by no means all.

For the paranoid: if you are going to start reversing things to
manually compensate for CPU endian-ness (for BitConverter usage), you
might also want to double-check that you need to!
BitConverter.IsLittleEndian will tell you how the CPU works. Itanium
leans the other way... so to speak.

Marc
Michael C - 16 Oct 2007 09:13 GMT
> from inspection, it appears to - hence my reply; valid in some
> circumstances, but by no means all.
[quoted text clipped - 3 lines]
> want to double-check that you need to! BitConverter.IsLittleEndian will
> tell you how the CPU works. Itanium leans the other way... so to speak.

Another option would be to convert the bytes back to short and then do
something like

if(BitConverter.IsLittleEndian) //or should that be not?
{
res = ((res & 0xff00) >> 8) || ((res & 0xff) << 8)
}

If res wasn't unsigned then might need to convert first. This might work
too:

res = (res >> 8) || (res << 8)

Michael
Marc Gravell - 16 Oct 2007 09:49 GMT
That should probably be a bitwise "or" (|), not a logical "or" (||).
And again, it only helps with a few cases (single, simple values like
short). IMO, the better solution is to leave the byte-stream alone,
and use EndianBitConverter. This will work for multiple sequenced
values, and all data types.

Marc
Kevin Spencer - 16 Oct 2007 17:00 GMT
Hi Michael,

Yes, it does reverse the order of an entire array. I should have mentioned
that this is part of a set of tools for parsing files, the most general of
the tools. I created it for working with GeoTiff images, which can be either
Big-Endian or Little-Endian. Once the Endian-ness of the file is determined,
the class actually sets a global variable, rather than passing a boolean
value to any function. Notice the BinaryReader instance parameter. This is
due to the fact that it is parsing a file.

The actual tool set has multiple methods that employ this method to read the
data in the file a "chunk" at a time. The data type of each "chunk" is
known, and passed to this method as the length parameter. There are
ReadShort, ReadLong, ReadInt32, ReadUInt32, ReadInt16, etc, methods that
employ this method.

I can understand your concern, as it is only the byte order within each
individual "chunk" of data that is reversed, and reading the entire file
into such a method would not work. I hope this clarifies your question.

Signature

HTH,

Kevin Spencer
Microsoft MVP

DSI PrintManager, Miradyne Component Libraries:
http://www.miradyne.net

>> Here is a  function I wrote that is designed for a BinaryReader:
>>
[quoted text clipped - 17 lines]
>
> Michael
Marc Gravell - 15 Oct 2007 05:06 GMT
Note that Jon Skeet has an EndianBitConverter (below) which may be of
use:

http://www.yoda.arachsys.com/csharp/miscutil/

Marc
Michael C - 15 Oct 2007 06:05 GMT
> Hello. I have a problem with getting short value from 2 byte array.
> I have this code. There are 2 short values in bytes.
[quoted text clipped - 12 lines]
>
> why it happends? How make BitConverter work correct?

You could just do cast[0] * 256 + cast[1]. You will need to work out how to
handle values of 128 or above for the first byte.

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.