在各种来源的帮助下,我在我的二进制阅读器类中编写了一些SwapBytes
方法,用于在ushort
,uint
和ulong
中交换endian,所有方法都使用所有在原始C#中的按位操作,不需要任何unsafe
代码。
public ushort SwapBytes(ushort x)
{
return (ushort)((ushort)((x & 0xff) << 8) | ((x >> 8) & 0xff));
}
public uint SwapBytes(uint x)
{
return ((x & 0x000000ff) << 24) +
((x & 0x0000ff00) << 8) +
((x & 0x00ff0000) >> 8) +
((x & 0xff000000) >> 24);
}
public ulong SwapBytes(ulong value)
{
ulong uvalue = value;
ulong swapped =
((0x00000000000000FF) & (uvalue >> 56)
| (0x000000000000FF00) & (uvalue >> 40)
| (0x0000000000FF0000) & (uvalue >> 24)
| (0x00000000FF000000) & (uvalue >> 8)
| (0x000000FF00000000) & (uvalue << 8)
| (0x0000FF0000000000) & (uvalue << 24)
| (0x00FF000000000000) & (uvalue << 40)
| (0xFF00000000000000) & (uvalue << 56));
return swapped;
}
我将如何创建相同的方法,但是对于每种类型的签名版本,例如short,int和long,只使用与上面相同的方法,以及可以对上述方法进行哪些改进?
答案 0 :(得分:14)
而不是从概念上解构为单独的字节,然后以相反的方式重新组合它们,你可以在概念上交换字节组,如下所示:(未经测试)
public uint SwapBytes(uint x)
{
// swap adjacent 16-bit blocks
x = (x >> 16) | (x << 16);
// swap adjacent 8-bit blocks
return ((x & 0xFF00FF00) >> 8) | ((x & 0x00FF00FF) << 8);
}
对于32位没有多大帮助(或者根本没有用),但对于64位它没有帮助(未经测试)
public ulong SwapBytes(ulong x)
{
// swap adjacent 32-bit blocks
x = (x >> 32) | (x << 32);
// swap adjacent 16-bit blocks
x = ((x & 0xFFFF0000FFFF0000) >> 16) | ((x & 0x0000FFFF0000FFFF) << 16);
// swap adjacent 8-bit blocks
return ((x & 0xFF00FF00FF00FF00) >> 8) | ((x & 0x00FF00FF00FF00FF) << 8);
}
对于签名类型,只需转换为无符号,执行此操作,然后转换回来。
答案 1 :(得分:7)
您应该查看以下msdn页面:http://msdn.microsoft.com/en-us/library/system.bitconverter.aspx
您可以简单地使用Array.Reverse和bitConverter:
int value = 12345678;
byte[] bytes = BitConverter.GetBytes(value);
Array.Reverse(bytes);
int result = BitConverter.ToInt32(bytes, 0);
答案 2 :(得分:2)
只需在开头添加一个转换为unsigned,然后返回到最后签名。
public long SwapBytes(long value)
{
return (long)SwapBytes((ulong)value);
}
可能需要手动内联调用SwapBytes
以获得最佳性能。
另外,您可能希望避免交换,而是直接以所需的字节顺序从原始字节数组中读取数据。有关详细信息,请参阅Efficient way to read big endian data in C#。
答案 3 :(得分:-1)
这可能是替换整数位的最简单和最懒惰的方法:
my $object = TiedThing->new({
lines => [join("\n", 1..9, 1..9)],
customvalue => "custom!",
});
say "can call custom method: " . $object->custom;
say "raw read with <>: " . <$object>;
my $buf;
read($object, $buf, 10);
say "raw read with read(): " . $buf;
undef $buf;
$object->read($buf, 10);
say "OO read via IO::File::read (end): " . $buf;
my $checksummer = Digest::MD5->new;;
$checksummer->addfile($object);
say "Md5 read: " . $checksummer->hexdigest;
my $dupto = IO::Handle->new;
# Doesn't break/return undef; still not usable without implementing
# more state sharing inside the object.
say "Can dup handle: " . $dupto->fdopen($object, "r");
my $archiver = Archive::Zip->new;
# Dies, but long after the fdopen() call. Can be fixed by implementing more
# PerlIO methods.
$archiver->readFromFileHandle($object);