一起Talk Android吧(第三百一十八回:Java中的类型转换)
Posted talk_8
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一起Talk Android吧(第三百一十八回:Java中的类型转换)相关的知识,希望对你有一定的参考价值。
各位看官们,大家好,上一回中咱们说的是android中虚拟按键的例子,这一回中咱们说的例子是Java中的类型转换。闲话休提,言归正转。让我们一起Talk Android吧!
我们在本章回中介绍Java类型转换的知识,主要是把十六进制形式的字符串转换成十六进制形式的字节数组,大家听着可能不明白,我举个例子来说明:string = "aa01cf"
转换成 byte[]=aa,01,cf.
注意byte数组中的aa是十六进制值,它的十进制值是170。
如何转换呢?我试过进制转换中常用的取模和取余算法,后来发现这些算法都不行,因为string中的aa无法直接转换成二进制编码,它可以转换成char,而char是ASCII编码,我需要把ASII码转换成二进制后再转换成十六进制。这样的操作太复杂了。我还试JDK中的各种方法,这些方法都无济于事,于是想到了使用脚本拆分字符串:
在每两个字符中间添加一个逗号,字符前面添加0x进行强制转换,使用拆分后的字符串手动给byte数组进行赋值。
下面是详细的代码,不过代码使用Java编写的,本来想用Python了,后来觉得Java操作字符串也很方便。转换的思路和方法都写到注释内容中了,大家可以参考:
/* 把字符串格式的命令转换成十六进制字节的byte数组,如果命令太长,写起来很麻烦
* 目前无法通过程序进行转换,因此使用手动的方法来转换,转换也很方便,操作如下:
* 把字符串格式的命令传到此方法中,运行后在控制台输出信息,然后复制信息到程序中
* 使用byte cmdData[] = new byte[]0xaa,0x01;来手动赋值,大括号中的内容
* 就是手动复制来的内容,注意末尾有一个逗号不需要复制.这种转换思想使用了脚本的思维。
*/
public String stringToHexByte(String string)
String cmdStr = string;
int length = cmdStr.length()/2;
int j =0 ;
int i =0;
StringBuilder sb = new StringBuilder();
String temp = null;
for(i=0,j=0; i<length; i++, j+=2)
temp = cmdStr.substring(j,j+2);
// sb.append("(byte)0x").append(temp).append(",");
sb.append(temp).append(" ");
后来发现这种转换对于固定的字符串有效果,对于程序中生成的字符串就不行了,因为string是在程序运行过程中生成的,而不是固定的内容。我于是想到了使用自定义码表的方式来转换,这个是受ASCII码表的启发。下面是具体的代码,转换的思路和方法都写到注释内容中了,大家可以参考:
/* 把十六进制的字符串转换成byte数组,例如: str = "a1b2" 转换成 byes[]=a1,b2;
* 转换思想:定义一个码表,其内容为0-f,每次从源字符串中取2个字符出来,第一个字符放到高字节,第二字符放到低字节
* 把取出的两个字符与码表做比较,如果和码表中的值相等,那么把码表的索引强制转换为byte型,虽然强制转换有损失
* 精度的风险,但是索引值是0-15,因此没有风险,为了降低风险还做了位的与操作。得到高低位的值后,把高位值向左
* 移动3位,然后与低位值进行或操作。合成后的值再做与OXFF做一次与操作,然后转换成byte类型。
* 注意源字符串中需需要是小写字母,因为码表中没有大写字母。
*/
public byte[] stringToHexBytes(String string)
/*//需要把字符串中的大写字母转换成小写字母,因为码表中没有大写字母 */
String str = string.toLowerCase();
//码表:用来和字符串中的字符做比较
String [] codeTable = new String[]"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f";
//码表的长度
int size = codeTable.length;
//源字符串的长度
int length = str.length();
//转换成byte的长度是源字符串长度的一半,因为是一个byte8位正好可以表示两个字符(0-f)
byte[] bytes = new byte[length/2];
byte highByte = 0x00;
byte lowByte = 0x00;
String subStr = null;
int index = 0;
for(int i=0; i<length; i+=2)
subStr = str.substring(i,i+2);
//get HighByte
for(int j=0; j<size; j++)
if(subStr.substring(0,1).equals(codeTable[j]))
highByte = (byte)(j & 0X00FF);
break;
//get LowByte
for(int j=0; j<size; j++)
if(subStr.substring(1,2).equals(codeTable[j]))
lowByte = (byte)(j & 0X00FF);
break;
if(index< length/2)
bytes[index] = (byte) (((highByte << 4) | lowByte) & 0XFF);
index += 1;
highByte = lowByte = 0x00;
return bytes;
最后我们可以编写一个程序来做验证,下面是完整的代码:
public class ExchangeFormat
public static void main(String args[])
String sourStr = "00ff0ff00990affa99aaaffa0990eb3a4daa9933bbb33b";
ExchangeFormat obj = new ExchangeFormat();
String desStr = obj.stringToHexByte(sourStr);
byte [] bytes = obj.stringToHexBytes(sourStr);
System.out.println("Method1: "+desStr);
System.out.print("Method2: ");
obj.showBytes(bytes);
/* 把字符串格式的命令转换成十六进制字节的byte数组,如果命令太长,写起来很麻烦
* 目前无法通过程序进行转换,因此使用手动的方法来转换,转换也很方便,操作如下:
* 把字符串格式的命令传到此方法中,运行后在控制台输出信息,然后复制信息到程序中
* 使用byte cmdData[] = new byte[]0xaa,0x01;来手动赋值,大括号中的内容
* 就是手动复制来的内容,注意末尾有一个逗号不需要复制.这种转换思想使用了脚本的思维。
*/
public String stringToHexByte(String string)
String cmdStr = string;
int length = cmdStr.length()/2;
int j =0 ;
int i =0;
StringBuilder sb = new StringBuilder();
String temp = null;
for(i=0,j=0; i<length; i++, j+=2)
temp = cmdStr.substring(j,j+2);
// sb.append("(byte)0x").append(temp).append(",");
sb.append(temp).append(" ");
/* 把十六进制的字符串转换成byte数组,例如: str = "a1b2" 转换成 byes[]=a1,b2;
* 转换思想:定义一个码表,其内容为0-f,每次从源字符串中取2个字符出来,第一个字符放到高字节,第二字符放到低字节
* 把取出的两个字符与码表做比较,如果和码表中的值相等,那么把码表的索引强制转换为byte型,虽然强制转换有损失
* 精度的风险,但是索引值是0-15,因此没有风险,为了降低风险还做了位的与操作。得到高低位的值后,把高位值向左
* 移动3位,然后与低位值进行或操作。合成后的值再做与OXFF做一次与操作,然后转换成byte类型。
* 注意源字符串中需需要是小写字母,因为码表中没有大写字母。
*/
public byte[] stringToHexBytes(String string)
/*//需要把字符串中的大写字母转换成小写字母,因为码表中没有大写字母 */
String str = string.toLowerCase();
//码表:用来和字符串中的字符做比较
String [] codeTable = new String[]"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f";
//码表的长度
int size = codeTable.length;
//源字符串的长度
int length = str.length();
//转换成byte的长度是源字符串长度的一半,因为是一个byte8位正好可以表示两个字符(0-f)
byte[] bytes = new byte[length/2];
byte highByte = 0x00;
byte lowByte = 0x00;
String subStr = null;
int index = 0;
for(int i=0; i<length; i+=2)
subStr = str.substring(i,i+2);
//get HighByte
for(int j=0; j<size; j++)
if(subStr.substring(0,1).equals(codeTable[j]))
highByte = (byte)(j & 0X00FF);
break;
//get LowByte
for(int j=0; j<size; j++)
if(subStr.substring(1,2).equals(codeTable[j]))
lowByte = (byte)(j & 0X00FF);
break;
if(index< length/2)
bytes[index] = (byte) (((highByte << 4) | lowByte) & 0XFF);
index += 1;
highByte = lowByte = 0x00;
return bytes;
public void showBytes(Byte [] bytes)
StringBuilder strBuilder = new StringBuilder("[");
String result = null;
// for (byte item: bytes)
// strBuilder.append(String.format("%x ", item));
//
// strBuilder.append(" ]");
// result = strBuilder.toString();
// System.out.println(result);
//使用上面或者下面的方法都可以输出十六进制,不过下面的方法可以控制输出宽度
System.out.print("[");
for(byte item: bytes)
System.out.printf("%2x ",item);
System.out.print("]");
在控制台中编译并且运行程序,结果如下:
javac ExchangeFormat.java
java ExchangeFormat
Method1: [00 ff 0f f0 09 90 af fa 99 aa af fa 09 90 eb 3a 4d aa 99 33 bb b3 3b ]
Method2: [ 0 ff f f0 9 90 af fa 99 aa af fa 9 90 eb 3a 4d aa 99 33 bb b3 3b ]
从运行结果可以看到,我们使用两种方法都可以对字符串进行转换,最重要的是转换后得到了相同的结果,有看官说部分值不一样,比如09和9不一样,实际上这个两个值在十六进制下是相等的,只是显示的时候没有显示9前面的0.
看官们,关于Java类型转换的例子咱们就介绍到这里,欲知后面还有什么例子,且听下回分解!
此外,本章回的内容我在工作遇到的问题,因此进行了总结和整理,如果大家有更加好的转换方法可以在评论区交流与讨论。
以上是关于一起Talk Android吧(第三百一十八回:Java中的类型转换)的主要内容,如果未能解决你的问题,请参考以下文章
一起Talk Android吧(第五百一十八回:在Android中使用MQTT通信五)
一起Talk Android吧(第三百一十九回:Android中网络通信之TCP概述)
一起Talk Android吧(第三百一十五回:Android中的ActionBar)
一起Talk Android吧(第三百一十四回:ImageView常用属性三)