从长字符串转换为四字符十六进制字符串

时间:2016-01-27 20:16:28

标签: java gps hex bytearray

更新的问题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?

预先感谢您的帮助,如果我再次遗漏任何必要的详细信息,我会道歉,如果您需要更多信息,请尽快再次更新。

2 个答案:

答案 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。