//发送数据
outputStream.write(“Hello World!”.getBytes());
outputStream.flush();
//关闭连接
outputStream.close();
socket.close();
- 我们来看下
OutputStream
的wirte(byte[] b)
函数 - OutputStream # write(byte[] b)
//1 接着又调用了write(byte b[], int off, int len)
public void write(byte b[]) throws IOException {
write(b, 0, b.length);
}
//2 最后又调用了write(byte b)
public void write(byte b[], int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if ((off < 0) || (off > b.length) || (len < 0) ||
((off + len) > b.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return;
}
//3 这里就是讲我们发送的一个bye[]进行for循环一个个写入了
for (int i = 0 ; i < len ; i++) {
write(b[off + i]);
}
}
//4 end
public abstract void write(int b) throws IOException;
小结:无论定义的通讯格式是什么样的最终肯定要转成byte[](字节数组)
进行发送,所以只要将数据转成字节数组即可,下面进入数据类型
科普时间
三、Java中的数据类型所占的字节数和bit数
数据类型 | 所占字节数 | 所占bit数 | 取值范围 |
---|---|---|---|
byte | 1 | 8 | -128 ~ 127 |
char | 2 | 16 | ‘\u0000’ ~ ‘\uFFFF’ |
short | 2 | 16 | -2^15 ~ 2^15 - 1 |
int | 4 | 32 | -2^31 ~ 2^31 - 1 |
float | 4 | 32 | 2^-149 ~ 2^128 -1 |
long | 8 | 64 | -2^63 ~ 2^63 - 1 |
double | 8 | 64 | 2^-1074 ~ 2^1024 - 1 |
boolean | / | 1 | true or false |
- String在Java中不属于基本数据类型,一个汉字占2个字节,一个英文字母占1个字节
- 小结:1 byte = 8 bit
3.1 什么是bit呢?什么又是高低位呢?在Java中又怎么写代码呢?
- bit就是
位
也就是二进制
数据,取值只有0
,1
- 高位在左,低位在右 - 这里以byte 123为例:
- byte b =123 转为bit
- 高位在0,低位在1
0111 1011
- 在Java中获取byte的8个bit
/**
-
byte转8 bit
-
@param b byte
-
@return 高位到低位顺序, 以byte123 为例: 0111 1011
*/
public static byte[] byte2Bit(byte b) {
byte[] arr = new byte[8];
for (int i = 7; i >= 0; i–) {
arr[i] = (byte) (b & 1);
b = (byte) (b >> 1);
}
return arr;
} -
既然把byte转为了8个bit位,那我们又怎么再把bit转回为byte呢?
/**
- 8个bit位转为byte
*/
public static byte bit2Byte(byte[] bytes) {
if (bytes.length != 8) return 0;
String binary = “”;
byte result;
for (byte b : bytes) {
binary += b;
}
if (bytes[0] == 0) {
// 正数
result = (byte) Integer.parseInt(binary, 2);
} else {
// 负数
result = (byte) (Integer.parseInt(binary, 2) - 256);
}
return result;
}
3.2 上面已经说了byte与bit的相互转化,现在就轮到int
了
- 上面已经说了一个
int
占4
个字节32
个bit
- Integer类已经为我们封装好了转bit的方法,如下:
String s = Integer.toBinaryString(35235);
//输出结果
1000100110100011
- 可以看到没有32位,这是为什么呢?这是因为高位都是为
0
所以就直接省略了,当然我们也可以主动补齐32
位只需要在高位补0
即可。 - bit再转回为int
int result = Integer.parseInt(“1000100110100011”, 2);
//输出结果
35235
- 这里需要注意的是Integer.toBinaryString()可以将负数转化为二进制,但是Integer.parseInt(“”, 2)不能直接将负数的二进制转为int,如下:
String radix = Integer.toBinaryString(-35235);
System.out.println(radix);
int result = Integer.parseInt(radix, 2);
System.out.println(result);
程序执行会报一个java.lang.NumberFormatException: For input string:"11111111111111110111011001011101"
异常,那我们怎么将负数的转回为int呢?当然是有方法的啦,如下:
//需要借助 BigInteger类
String radix = Integer.toBinaryString(-3535);
BigInteger integer = new BigInteger(radix, 2);
System.out.println(integer.intValue());
//输出结果
-3535
3.3当然我们可以通过电脑的计算器来计算二进制
3.4 上面我们说了一个int
占32
个字节也就是4
个byte
,那理所当然一个int
可以转成2个byte或者4
个byte
,如下:
/**
- 一个int转2个字节的byte数组
- 由低位到高位的转换
- @param value
- @return
*/
public static byte[] intTo2Bytes(int value) {
byte[] src = new byte[2];
src[0] = (byte) (value & 0xFF);
src[1] = (byte) ((value >> 8) & 0xFF);
return src;
}
/**
- 一个int转4个字节的byte数组
- 由低位到高位的转换
- @param value
- @return
*/
public static byte[] intTo4Bytes(int value) {
byte[] src = new byte[4];
src[0] = (byte) (value & 0xFF);
src[1] = (byte) ((value >> 8) & 0xFF);
src[2] = (byte) ((value >> 16) & 0xFF);
src[3] = (byte) ((value >> 24) & 0xFF);
return src;
}
这里需要注意的是
int转byte[]
的时候是高位
在数组的0下标
还是低位
在数组的0下标
,上面的两个方法都是低位在数组的0下标
四、上面bb了一大堆,现在我们通过一个具体的协议来深入了解这些内容
4.1 协议如下:
这里需要解释下
uchar
、uint
是什么意思?uchar = unsigned char 、uint = unsigned int,也就是无符号的数据,也就是表示了这个数据是正数
- 1、对协议进行分析可以得知:整个数据包是由两部分组成的
包头
+扩展数据包
,其中包头占固定的32个字节 - 2、首先我们得分析包头里面的每一个字段所占了多少个
字节
- uchar 占1个字节
- uint 占4个字节
- 2、那我们重点就是得来分析包头的数据需要怎么封装,通过协议我们可以看出
包头
内一共包含6个字段,分别表示如下: - 第一个为固定的
"DH"
,总共占2
个字节 - 第二个为版本
1.0
,总共占2
个字节 - 第三个为扩展数据长度
"extlen"
,总共占4
个字节 - 第四个为扩展数据类型
取值0或1
,总共占1
个字节 - 第五个为保留字段不使用就
0
补齐,总共占3
个字节 - 第六个为保留字段不使用就
0
补齐,总共占20
个字节 - 3、通过上面一顿分析,我们就轻松的理清了每个字段所占的字节了
4.2 Talk is cheap. Show me the code.
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
结尾
我还总结出了互联网公司Android程序员面试涉及到的绝大部分面试题及答案,并整理做成了文档,以及系统的进阶学习视频资料分享给大家。
(包括Java在Android开发中应用、APP框架知识体系、高级UI、全方位性能调优,NDK开发,音视频技术,人工智能技术,跨平台技术等技术资料),希望能帮助到你面试前的复习,且找到一个好的工作,也节省大家在网上搜索资料的时间来学习。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
开发,音视频技术,人工智能技术,跨平台技术等技术资料),希望能帮助到你面试前的复习,且找到一个好的工作,也节省大家在网上搜索资料的时间来学习。**
[外链图片转存中…(img-98Ki5siG-1712375689067)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!