1.进制
进制是什么?进制不是孤立存在的,了解进制之前需要先了解数制。
记数系统,或称记数法或数制。是使用一组数字符号来表示数的体系。
一个理想的记数系统能够:1.有效地描述一组数(例如,整数、实数)2.所有的数对应唯一的表示(至少有一个标准表示法)3.反映数的代数和算术结构
记数系统可以按照以下方式分类:
按照进位制,可分为十进制、二进制、八进制等。按照写法,可分为中文数字、阿拉伯数字、罗马数字等。
如何记数?这就是靠进位制了。
名称 | 基数 | 进位 |
---|---|---|
二进制 | 0,1 | 逢2进1 |
八进制 | 0,1,2,3,4,5,6,7 | 逢8进1 |
十进制 | 0,1,2,3,4,5,6,7,8,9 | 逢10进1 |
十六进制 | 0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f | 逢16进1 |
下面是二进制与八进制转换。
二进制 → 八进制
方法:取三合一法,即从二进制的小数点为分界点,向左(向右)每三位取成一位,接着将这三位二进制按权相加,然后,按顺序进行排列,小数点的位置不变,得到的数字就是我们所求的八进制数。如果向左(向右)取三位后,取到最高(最低)位时候,如果无法凑足三位,可以在小数点最左边(最右边),即整数的最高位(最低位)添0,凑足三位。
例:将二进制的(11010111.0100111)B转换为八进制的步骤如下:
- 小数点前111 = 7;
- 010 = 2;
- 11补全为011,011 = 3;
- 小数点后010 = 2;
- 011 = 3;
- 1补全为100,100 = 4;
- 读数,读数从高位到低位,即(11010111.0100111)B=(327.234)O。
https://www.cnblogs.com/gaizai/p/4233780.html
八进制 → 二进制
https://www.cnblogs.com/gaizai/p/4233780.html
方法:取一分三法,即将一位八进制数分解成三位二进制数,用三位二进制按权相加去凑这位八进制数,小数点位置照旧。
例:将八进制的(327)O转换为二进制的步骤如下:
-
3 = 011;
-
2 = 010;
-
7 = 111;
-
读数,读数从高位到低位,011010111,即(327)O=(11010111)B。
更多转换,可参考这个:
二、八、十、十六进制转换(图解篇)
2.字符
计算机中处理的数据有两类:数值数据和非数值数据。数值数据指表示数量的数据,有正负和大小之分,在计算机中以二进制的形式存储和进行运算。非数值数据包括字符、汉字、声音和图像等,在计算机中处理前必须以某种编码形式转换成二进制数表示(例如ASCII表)。
编码是信息从一种形式或格式转换为另一种形式的过程,也称为计算机编程语言的代码简称编码。用预先规定的方法将文字、数字或其它对象编成数码,或将信息、数据转换成规定的电脉冲信号。编码在电子计算机、电视、遥控和通讯等方面广泛使用。编码是信息从一种形式或格式转换为另一种形式的过程。解码,是编码的逆过程。
字符,在计算机中处理前必须以某种编码形式转换成二进制数表示。什么是字符?有哪几种常见编码形式?
简单地看下 字符的概念。
字符(character)是一段文字的最小单位,它可能是汉字、阿拉伯数字、英文字母、日语假名、标点符号或其他有意义的内容。
常见编码格式有ASCII、ISO-8859-1、GB2312、GBK、UTF-8、UTF-16、Unicode等。
例如ASCII 码表中的字符 *
,计算机要如何识别该数据呢?这就需要解码了。凡是有编码的地方,就需要解码。这里计算机需要对应ASCII码表去解码。 *
对应二进制数值为0010 1010。
unicode是字符集,utf-8、utf-16等是表现形式(编码方式,类似于中文跟行书、楷书等的关系)。
Unicode 是 Java 和 XML 的基础。
Unicode译为万国码、国际码。Unicode是为了解决传统的字符编码方案的局限而产生的,例如ISO 8859-1所定义的字符虽然在不同的国家中广泛地使用,可是在不同国家间却经常出现不兼容的情况。
Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符。
Unicode只是一个符号集, 它只规定了符号的二进制代码, 却没有规定这个二进制代码应该如何存储(因此有了utf-8 -16 -32)。
比如UTF-8、UTF-16、UTF-32都是Unicode编码的实现方式,不过UTF-8是使用最多的实现。
下面的链接是在网上搜到的Unicode编码表:
https://pan.baidu.com/s/1slg2Pit
可以直接通过表查看字符在编码表对应的数据(十六进制)。
通过查看不同的编码表可以看出,同一个字符,在不同的编码表中,对应的数据是不同的,例如!
,在ASCII 和unicode表中的位置是不同的,数据不一致。
其实还可以直接使用Notepad++的插件查看,下面来直接查看UTF-8 的编码格式对应的数据。
在安装完所需插件(HEX-Editor)后,新建txt文档,写下“如”字。
image然后使用插件,查看对应的utf-8的十六进制数据。
image可以自己修改编码格式,然后查看对应的十六进制数据。
字符串是由数字、字母、下划线组成的一串字符。
3.转换函数
3.1 int和String之间的转换
由于数据类型较多,所以这里先通过简单看一个十六进制int数据A5转换成十进制int 数据165来看看那些常用API。
3.1.1 十六进制int转十进制int
//定义一个十六进制数据 A5 ,需要转换成十进制int 165
int hexInt = 0xA5;
首先需要把int转换成String。这里有个要注意的地方,如果直接使用+ ""
去转换的话,会把0xA5
转为十进制的165。
String test = hexInt + ""
会产生两个String对象,首先会把十六进制的int转换,生成一个存放十进制数据的String,最后得到的数据是"165"
这个字符串。如果得到了"165"
这个字符串,可以通过Integer.valueOf(test,10)
,获得Integer
数据。 Integer
自动拆箱。
int hexInt = 0xA5;
String test = hexInt + "";
//Integer 自动拆箱
int decInt = Integer.valueOf(test, 10);
Log.d(TAG,"test >> 十进制 int :" + test + " >> "
+ decInt );
打印结果如下
如果想得到"a5"
这个字符串,再去转换进制,需要使用
Integer.toString(hexInt,16)
或Integer.toHexString(hexInt)
,把十六进制的int数据转化为十六进制的String,再使用 Integer.parseInt(hexString,16)
返回一个十进制的int数据(Integer.parseInt(String s,int radix)返回的结果是一个十进制数)。
如果需要返回Integer类型,就使用Integer.valueOf
。parseInt效率比valueof效率高,valueof就是调用了parseInt方法的,并且多了一个装箱的操作,将int封装为Integer。
int hexInt = 0xA5;
//把十六进制的int 转换成十六进制的String
String hexString = Integer.toString(hexInt,16);
Log.d(TAG,"十六进制 hexString >> 十进制 int :" + hexString + " >> "
+ Integer.parseInt(hexString,16) );
打印结果如下
image.png
如果想得到大写的A5
,那么需要调用String
中的toUpperCase
函数。
public String toUpperCase() {
return toUpperCase(Locale.getDefault());
}
转换的基本流程是:
1.int先转String
2.进制转换
3.String再转回int。
实际上Integer 把1和2合并。
这里Integer.toString
其实还可以直接把十六进制的int,转换成十进制的String。如果不需要把string转int的话,这样就可以了。
int hexInt = 0xA5;
//把十六进制的int 转换成十进制的String
String decString = Integer.toString(hexInt,10);
Log.d(TAG,"十进制 decString >> 十进制 int :" + decString + " >> "
+ Integer.parseInt(decString,10) );
打印结果如下
image.png
3.1.2 int转String
int转string,Integer
中有如下方法。
其实String也有函数可以使用,
format
和valueOf
。image.png
image.png
String.format("%d", hexInt)
和String.valueOf(int i)
,返回十进制的String。
以 十六进制 int数据 >> 十进制String 为例,转十进制String有如下几种方法。
int hexInt = 0xA5;
//转十进制String
Log.d(TAG,"Integer.toString(hexInt,10): " + Integer.toString(hexInt,10)
+ " Integer.toString(hexInt): " + Integer.toString(hexInt)
+ "+字符串连接 : " + (hexInt+"")
+ " String.format: " + String.format("%d", hexInt)
+ " String.valueOf(hexInt): "+ String.valueOf(hexInt));
log如下
Integer.toString(hexInt,10): 165 Integer.toString(hexInt): 165+字符串连接 : 165 String.format: 165 String.valueOf(hexInt): 165
以 十六进制 int数据 >> 十六进制String 为例,转十六进制String方法如下:
int hexInt = 0xA5;
//转十六进制String
Log.d(TAG,"Integer.toString(hexInt,16): " + Integer.toString(hexInt,16)
+ " Integer.toHexString(hexInt): " + Integer.toHexString(hexInt)
+ " String.format %x: " + String.format("%x", hexInt));
log如下
Integer.toString(hexInt,16): a5 Integer.toHexString(hexInt): a5 String.format %x: a5
需要转换成其他进制,例如二进制String的话,就把16换成2,toHexString换成toBinaryString。
int hexInt = 0xA5;
//转二进制String
Log.d(TAG,"Integer.toString(hexInt,2): " + Integer.toString(hexInt,2)
+ " Integer.toBinaryString(hexInt): " + Integer.toBinaryString(hexInt));
Integer.toString(hexInt,2): 10100101 Integer.toBinaryString(hexInt): 10100101
3.1.3 String转int
Integer中有如下方法
image.png
image.png
十六进制String >> 十进制 int数据方法如下:
String hexString = "A5";
//十六进制string 转 十进制int
Log.d(TAG,"Integer.parseInt(hexString,16): " + Integer.parseInt(hexString,16)
+ " Integer.valueOf(hexString,16): " + Integer.valueOf(hexString,16));
log如下
Integer.parseInt(hexString,16): 165 Integer.valueOf(hexString,16): 165
其他进制,例如十进制String,需要转换成十进制的int数据的话,也是使用parseInt。
String decString = "165";
//十进制string 转 十进制int
Log.d(TAG,"Integer.parseInt(decString,10): " + Integer.parseInt(decString,10)
+ " Integer.valueOf(decString): " + Integer.valueOf(decString));
log如下
Integer.parseInt(decString,10): 165 Integer.valueOf(decString): 165
这里好像只有转为十进制int的方法。十六进制的string没有转为十六进制int的方法。
最常用的2个函数toString
和parseInt
:
Integer.toString(int,16):
int转换成的十六进制的String后返回
Integer.parseInt(string,16)
返回从十六进制的string中解析出的int
常用String间进制转换
Log.d(TAG,"二进制 >> 十六进制: " + Integer.toString(0b111,16)
+ " 十进制 >> 二进制: " + Integer.toString(12,2)
+ " 十六进 >> 十进制: " + Integer.toString(0x111,10)
+ " 十进制 >> 十六进制: " + Integer.toString(12,16)
);
log如下
二进制 >> 十六进制: 7 十进制 >> 二进制: 1100 十六进 >> 十进制: 273 十进制 >> 十六进制: c
注意:要是数据太大,就要用BigInteger
4.String与byte[]的转换
1.字节数组转16进制字符串
/*
* 字节数组转16进制字符串
*/
public static String bytes2HexString(byte[] b) {
String r = "";
for (int i = 0; i < b.length; i++) {
String hex = Integer.toHexString(b[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
r += hex.toUpperCase();
}
return r;
}
public static String byteToString(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
sb.append(String.format("%02X", bytes[i]));
}
return sb.toString();
}
2.16进制字符串转字节数组
/**
* 将16进制字符串转换为byte[]
*
* @param str
* @return
*/
public static byte[] hexToBytes(String str) {
if(str == null || str.trim().equals("")) {
return new byte[0];
}
byte[] bytes = new byte[str.length() / 2];
for(int i = 0; i < str.length() / 2; i++) {
String subStr = str.substring(i * 2, i * 2 + 2);
bytes[i] = (byte) Integer.parseInt(subStr, 16);
}
return bytes;
}
简单测试一下这函数。
try {
byte[] bytes = "测试".getBytes("utf-8");
String str = "e6b58be8af95";
Log.d(TAG, "字节数组为: " + Arrays.toString(bytes)
+ " byteToString = " + byteToString(bytes)
+ " hexToBytes = " + Arrays.toString(hexToBytes(str))
+ " byte[] 转 utf-8字符: " + new String(hexToBytes(str), "utf-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
log如下
字节数组为: [-26, -75, -117, -24, -81, -107] byteToString = E6B58BE8AF95 hexToBytes = [-26, -75, -117, -24, -81, -107] byte[] 转 utf-8字符: 测试
- byte转化成2进制字符串
/**
* 把byte转化成2进制字符串
* @param b
* @return
*/
public static String getBinaryStrFromByte(byte b){
String result ="";
byte a = b; ;
for (int i = 0; i < 8; i++){
byte c=a;
a=(byte)(a>>1);//每移一位如同将10进制数除以2并去掉余数。
a=(byte)(a<<1);
if(a==c){
result="0"+result;
}else{
result="1"+result;
}
a=(byte)(a>>1);
}
return result;
}
byte aByte = (byte) 0xA5;
Log.d(TAG," byte = " + aByte + " getBinaryStrFromByte = "+ getBinaryStrFromByte(aByte));
log如下。
byte = -91 getBinaryStrFromByte = 10100101
4.byte[]和string转换还有一个乱码的问题要注意。
乱码问题根源:编码与解码所用的字符编码方式不一致
byte[] b_GBK = "中国".getBytes("GBK");
byte[] b_UTF8 = "中国".getBytes("UTF-8");
byte[] b_ISO88591 = "中国".getBytes("ISO8859-1");
//对字节数组按照指定的字符编码方式解码
System.out.println(new String(b_UTF8, "UTF-8"));
System.out.println(new String(b_UTF8, "ISO8859-1"));
System.out.println(new String(b_ISO88591, "UTF-8"));
运行结果
中国
ä¸å›½
??
第二行乱码因为:编码UTF-8,解码ISO8859-1,编解码所用的字符编码方式不一致
第三行乱码因为:编码ISO8859-1,解码UTF-8,编解码所用的字符编码方式不一致
只有保持编解码所用的字符编码方式一致就可以避免乱码。
5.String和Ascii的相互转化
java八进制、十进制、十六进制(hex)ASCII码字符串和String互转
在做Android
串口开发的时候,与串口设备间的通信经常内容都是16进制的。发送命令的时候需要先把命令转成16进制的ASCII
字符串。接收到设备的反馈时需要把16进制的ASCII
字符串转成对应的明文。
比如我们要 发送 的明文为ABCDEF
,需要先转成对应的16进制ASCII码字符串414243444546
,我们 收到 的反馈为16进制的ASCII
码字符串313233343536
,需要转成对应的明文123456
。
1.16进制ASCII码和单个字符char的互转
// hex转char
// 先将hex字符串转成int
int i = Integer.parseInt("46", 16);
// hex转char方法一,结果为F
String str1 = new String(new char[]{(char)i});
// hex转char方法二,结果为F
String str2 = new StringBuffer().append((char)i).toString();
// char转hex方法一,结果为46(第二个参数16表16进制)
String hex1 = Integer.toString(c, 16);
// char转hex方法二,结果为46
String hex2 = Integer.toHexString('F');
2.ASCII码hex字符串转String明文
每两个字符表示的16进制ASCII码解析成一个明文字符
public static String hex2Str(String hex) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hex.length() - 1; i += 2) {
String h = hex.substring(i, (i + 2));
int decimal = Integer.parseInt(h, 16);
sb.append((char) decimal);
}
return sb.toString();
}
// 输出结果为ABCDEF
System.out.println(hex2Str("414243444546"));
3.String明文转ASCII码hex字符串
一个明文字符生成两个字符表示的16进制ASCII码
public static String str2Hex(String str) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
// 这里的第二个参数16表示十六进制
sb.append(Integer.toString(c, 16));
// 或用toHexString方法直接转成16进制
// sb.append(Integer.toHexString(c));
}
return sb.toString();
}
// 输出结果为414243444546
System.out.println(str2Hex("ABCDEF"));
4.十进制ASCII码字符串和String明文互转
10进制的转换和16进制的类似,只有细微的差别,直接看代码
10进制ASCII转String
public static String dec2Str(String ascii) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < ascii.length() - 1; i += 2) {
String h = ascii.substring(i, (i + 2));
// 这里第二个参数传10表10进制
int decimal = Integer.parseInt(h, 10);
sb.append((char) decimal);
}
return sb.toString();
}
// 结果为ABCDEF
System.out.println(dec2Str("656667686970"));
String转10进制ASCII
public static String str2Dec(String str) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
// 第二个参数10表示10进制
sb.append(Integer.toString(c, 10));
// 或者省略第二个参数,默认为10进制
// sb.append(Integer.toString(c));
}
return sb.toString();
}
// 结果为656667686970
System.out.println(str2Dec("ABCDEF"));
5.八进制ASCII码字符串和String明文互转
八进制ASCII码的转换也类似,主要要注意的地方是八进制的ASCII码占三位,而16进制和十进制表示法只占两位
8进制ASCII转String
public static String oct2Str(String ascii) {
StringBuilder sb = new StringBuilder();
// 这里这里循环的步进为3,因为8进制的ASCII码占3位
for (int i = 0; i < ascii.length() - 2; i += 3) {
String h = ascii.substring(i, (i + 3));
// 第二个参数8表8进制
int decimal = Integer.parseInt(h, 8);
sb.append((char) decimal);
}
return sb.toString();
}
// 结果为ABCDEF
System.out.println(oct2Str("101102103104105106"));
String转8进制ASCII
public static String str2Oct(String str) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
// 这里的第二个参数8表8进制
sb.append(Integer.toString(c, 8));
// 或者直接用toOctalString方法转8进制
// sb.append(Integer.toOctalString(c));
}
return sb.toString();
}
// 结果为101102103104105106
System.out.println(str2Oct("ABCDEF"));
参考链接:
二、八、十、十六进制转换(图解篇)
https://tool.oschina.net/apidocs/apidoc?api=jdk-zh
java八进制、十进制、十六进制(hex)ASCII码字符串和String互转
Java字节、十进制、十六进制、字符串之间的相互转换
java byte[]与十六进制字符串相互转换
Java中二进制字节与十六进制互转
String.getBytes和new String 出现乱码问题分析
Android String通过蓝牙串口byte[]传送后转成String
网友评论