我正在尝试将一些使用BitConverter的现有C#代码移植到Java。我找到了各种其他线程,但后来发生在github类似乎可以解决这个问题。但是,ToUInt16与我的C#代码的输出不匹配。 ToInt16和ToInt32似乎返回相同的值。你能帮我理解这个实现有什么问题(或者我可能做错了吗?)
代码参考:Java BitConverter
ToUInt16:
public static int ToUInt16(byte[] bytes, int offset) {
int result = (int)bytes[offset+1]&0xff;
result |= ((int)bytes[offset]&0xff) << 8;
if(Lysis.bDebug)
System.out.println(result & 0xffff);
return result & 0xffff;
}
ToUInt32:
public static long ToUInt32(byte[] bytes, int offset) {
long result = (int)bytes[offset]&0xff;
result |= ((int)bytes[offset+1]&0xff) << 8;
result |= ((int)bytes[offset+2]&0xff) << 16;
result |= ((int)bytes[offset+3]&0xff) << 24;
if(Lysis.bDebug)
System.out.println(result & 0xFFFFFFFFL);
return result & 0xFFFFFFFFL;
}
MyCode代码段
byte[] byteArray = from some byte array
int offset = currentOffset
int msTime = BitConverter.ToUInt16(byteArray, offset)
msTime与来自C#
的内容不匹配C#示例(来自供应商的字符串使用Convert.FromBase64String从字符串转换)
byte[] rawData = Convert.FromBase64String(vendorRawData);
byte[] sampleDataRaw = rawData;
Assert.AreEqual(15616, sampleDataRaw.Length);
//Show byte data for msTime
Console.WriteLine(sampleDataRaw[7]);
Console.WriteLine(sampleDataRaw[6]);
//Show byte data for msTime
Console.WriteLine(sampleDataRaw[14]);
Console.WriteLine(sampleDataRaw[13]);
var msTime = BitConverter.ToUInt16(sampleDataRaw, 6);
var dmWindow = BitConverter.ToUInt16(sampleDataRaw, 13);
Assert.AreEqual(399, msTime);
Assert.AreEqual(10, dmWindow);
C#控制台输出字节值:
1
143
0
10
Groovy示例(来自供应商的字符串使用groovy decodeBase64()从字符串转换)
def rawData = vendorRawData.decodeBase64()
def sampleDataRaw = rawData
Assert.assertEquals(15616, rawData.length)
//Show byte data for msTime
println sampleDataRaw[7]
println sampleDataRaw[6]
//Show byte data for dmWindow
println sampleDataRaw[14]
println sampleDataRaw[13]
def msTime = ToUInt16(sampleDataRaw, 6)
def dmWindow = ToUInt16(sampleDataRaw, 13)
Assert.assertEquals(399, msTime)
Assert.assertEquals(10, dmWindow)
**Asserts fail with**
399 fro msTime is actually 36609
10 from dmWindow is actually 2560
来自println中字节值的Groovy输出
1
-113
0
10
答案 0 :(得分:2)
这两种方法之间存在差异。第一个ToUInt16
采用big-endian字节顺序。即第一个字节是最重要的字节。
但ToUInt32
假定小端字节顺序(一个奇怪的选择)。所以第一个字节最不重要。
更正的实施方式如下:
public static long toUInt32(byte[] bytes, int offset) {
long result = Byte.toUnsignedLong(bytes[offset+3]);
result |= Byte.toUnsignedLong(bytes[offset+2]) << 8;
result |= Byte.toUnsignedLong(bytes[offset+1]) << 16;
result |= Byte.toUnsignedLong(bytes[offset]) << 24;
return result;
}
数组索引已被反转&#39;
(我也改变了hacky看的bitmasking更清晰的调用Byte.toUnsignedLong
,这也做同样的事情。)
答案 1 :(得分:0)
我实际发现的是,ToInt16实际上是在给我我想要的结果,而不是解决方案中的ToUInt16。我检查了很多结果,它们都匹配.Net输出。
来自@ pinkfloydx33的link我可以看到源代码,实际上是我尝试使用ToInt16而不是ToUInt16的原因。