更新的问题01/28/2016:
由于之前我的问题并不十分清楚(我还在学习),这里重写了我的帖子:
以下是我发现自己的情景:
我写了一些代码,这些代码从日志文件中读取数据,该日志文件包含以下列格式以十六进制格式化的GPS坐标:
“X1 X2 X3 X4 Y1 Y2 Y3 Y4”
其中X是纬度分量而Y是经度分量。我的代码通过基本上执行以下序列将这些消息转换为纬度/经度值(以度为单位):
String strHexLat = X1 + X2 + X3 + X4; //(X1X2X3X4 viewed as one hex value)
String strHexLon = Y1 + Y2 + Y3 + Y4; //(Y1Y2Y3Y4 viewed as one hex value)
int intLat = Integer.decode(strHexLat);
int intLon = Integer.decode(strHexLon);
if ((intLat & 0x40000000) != 0) {
intLat |= 0x80000000;
}
if ((intLon & 0x40000000) != 0) {
intLon |= 0x80000000;
}
double lat = (double) intLat / 3600000; // convert from MAS to DEG
double lon = (double) intLon / 3600000; // convert from MAS to DEG
尽管不是特别优雅,上面的代码做了我想要的。我真正的麻烦开始的地方是扭转过程。我正在尝试编写一些代码,现在将以与现有文件相同的格式创建日志文件,从坐标开始并生成表示坐标的8字符十六进制数组。
以下片段是我目前要执行此转换的内容,以及样本输入,结果输出和所需输出:
(1)将坐标转换为毫秒:
/* TEST COORDINATES */
mLat = 42.281422;
mLon = -83.748552;
/* Convert values from degrees to milliarcseconds*/
long convLat = (long)(mLat * 3600000.0);
long convLon = (long)(mLon * 3600000.0);
输入:
mLat = 42.281422
mLon = -83.748552
输出:
convLat = 152213119
convLon = -301494787
期望的输出:
以上输出符合要求。
(2)负值的说明:
/* Account for negative values */
if(convLat < 0) convLat = convLat & 0x00000000ffffffffL;
if(convLon < 0) convLon = convLon & 0x00000000ffffffffL;
输入:
convLat = 152213119
convLon = -301494787
输出:
convLat = 152213119
convLon = 3993472509
期望的输出:
以上输出符合要求。
(3)将值拆分为4个值(暂时仅尝试使用纬度分量):
/* Split into four values */
byte[] dataLat = new byte[4];
dataLat[0] = (byte) ( ( convLat >>> 24 ) & 0xff );
dataLat[1] = (byte) ( ( convLat >>> 16 ) & 0xff );
dataLat[2] = (byte) ( ( convLat >>> 8 ) & 0xff );
dataLat[3] = (byte) ( ( convLat >>> 0 ) & 0xff );
输入:
convLat = 152213119
输出:
dataLat[0] = 9
dataLat[1] = 18
dataLat[2] = -106
dataLat[3] = 127
期望的输出:
*****我不完全确定负值。
(4)将值转换为单个十六进制字符串:
/* Convert to 1 hex string per component */
String hexLat = Long.toHexString(convLat);
String hexLon = Long.toHexString(convLon);
输入:
convLat = 152213119
convLon = 3993472509
输出:
hexLat = "912967f"
hexLon = "ee078dfd"
期望的输出:
这些值有效,可以转换回所需的度数值。
如果:
convLat = 152213119被转换为“912967f”
我想:
convLat = 152213119成为“09 12 96 7f”
其中:
四个十六进制值中的任何一个都可以是1或2位数,并且在左边用0填充,在这种情况下它只是第一个数字,但它可以是四个中的任何一个。
(5)将值转换为4个十六进制字符串:
/* Convert to 4 hex strings per component */
String[] hexStringLat = new String[4];
hexStringLat[0] = Integer.toHexString(dataLat[0]);
hexStringLat[1] = Integer.toHexString(dataLat[1]);
hexStringLat[2] = Integer.toHexString(dataLat[2]);
hexStringLat[3] = Integer.toHexString(dataLat[3]);
输入:
dataLat[0] = 9
dataLat[1] = 18
dataLat[2] = -106
dataLat[3] = 127
输出:
hexStringLat[0] = "9"
hexStringLat[1] = "12"
hexStringLat[2] = "ffffff96"
hexStringLat[3] = "7f"
期望的输出:
转换为单个十六进制字符串时,我们得到值“912967f”
我希望以上面提到的四个字符串的形式,“09 12 96 7f”。
然而,当直接转换为四个十六进制值时,我得到“9 12 ffffff96 7f” 在这种情况下,填充操作很简单,但我不希望3值为负值。
问题:
为什么在直接转换为四个十六进制字符时第三个值为负,而在转换为仅一个十六进制字符串时则不是?
是否有'简单'的方法将单个字符串转换为我想要的格式?
我可以编写一些草率的代码来运行单个代码,它会尝试不同的方法来分割值,然后测试字符串转换回来,但这似乎是错误的方法。
注意:
我发现以下内容有些帮助,但对于我所处的场景并不完整:
How to perform unsigned to signed conversion in Java?
预先感谢您的帮助,如果我再次遗漏任何必要的详细信息,我会道歉,如果您需要更多信息,请尽快再次更新。
答案 0 :(得分:0)
由于你已经有lat和long的十六进制字符串,为什么不简单地拆分它,
Matcher m = Pattern.compile(".{1,2}").matcher(hexLat.toUpperCase());
String s1 = m.find() ? hexLat.substring(m.start(), m.end()) : "";
String s2 = m.find() ? hexLat.substring(m.start(), m.end()) : "";
String s3 = m.find() ? hexLat.substring(m.start(), m.end()) : "";
String s4 = m.find() ? hexLat.substring(m.start(), m.end()) : "";
答案 1 :(得分:0)
我没有测试过这个,但你不能使用String.format吗?
String.format ("%02X %02X %02X %02X", (byte) ( ( convLat >>> 24 ) & 0xff ),
等。
也就是说,突破每个字节,正如您已经通过移位和屏蔽所做的那样,并将它们作为参数传递给String.format。
02确保两位数,必要时添加前导零。大写字母X表示使用十六进制并使用大写字母A-F。