前言
最近在做一个远程屏幕共享软件,功能非常单一,只能通过Android端查看电脑的实时屏幕,一开始做法是电脑端不停捕获当前屏幕截图,压缩后上传到服务器,Android不停的刷新,但是结果有点不尽人意,效果太差了。其中并没有将捕获的屏幕保存成jpg,然后发送,而是直接将BufferedImage转换成 byte[]发送,当然服务器也没有存成文件,也是使用byte[]存最新的屏幕数据,Android通过给定接口将byte[]转换成图像。
这里面有个将InputStream中的数据转换成BufferedImage的逻辑,我们可以使用 ImageIO这个类。
但是经过测试,JPEGCodec这个类似乎更好一些,但不知是不是如此,我不太确定。(ImageIO出现过错误,反而JPEGCodec却没有),但是注意的是,JPEGCodec并不属于Java APIs的一部。
另外内存也占的太多,这归根到底,是自己不会高深算法,哎。
于是也企图研究一下,后来通过Socket来完成,这回延时也比较低,但是是属于直连的形式,也就是手机通过Socket直接怼到电脑,电脑端不停的发送屏幕数据,可能在同一个局域网,速度也比较快。另外经过优化,内存、CPU使用率都不是很高,窗口在拖动时Android端也差不多能流畅的显示。
但是要做的并不是如此,不想只限制在局域网中,所以,我需要一个数据中转服务器。
电脑和Android通过Socket连接到服务器,服务器收到电脑发送的数据后传递给所有Android端。恩,大致是这样。
但是也遇到很多问题,如我要自定义一个格式,要将int转byte[],byte[]在转int,我想有必要记录下转换过程。
int转byte
在java中,int为8字节,二进制为32位,范围在2147483648——2147483647之间,而byte在-128~127之间,那int转byte就有些小计算了,大桶不可能完全放进小桶内,那么这样转换逼不得已要把大桶敲碎,把一小块放进小桶内,这会导致什么?当然是转换后的值不一定是原来的值了。
下面这个输出的byteValue也等于intValue,这是因为还没有越界,byte还能容纳。
public static void main(String[] args) {
int intValue =123;
byte byteValue =(byte)intValue;
System.out.println(byteValue);//123
}
好,再看下一个,这回输出为-69,想知道内部是怎么转换的吗?
public static void main(String[] args) {
int intValue =187;
byte byteValue =(byte)intValue;
System.out.println(byteValue);
}
在上面我们说过,要把大桶敲碎,在装进去,在这里,我要就要把int敲碎,要敲那部分呢?当然是敲他二进制的后8位。(此时我们要明白Java是采用补码存储整数)
首先把187转换为二进制。
00000000 00000000 00000000 10111011
然后敲出他的后8位,(补码表示的时候第一位是符号位,0为正数,1为负数,剩余是他的数值部分),所以他是一个负数,这也是为什么输出负数的原因。
1011 1011
然后将他的数值部分取反后+1(符号位不变)。
011 1011(7位数值部分)
100 0100(7位数值部分) //取反
100 0101(7位数值部分) //+1
然后直接算100 0101的十进制为69,又因为最高位是1,所以他是负数,为-69,这里要注意的是,不能算符号位,如果最终也算符号位的话,那么基本数据类型的范围将不是现在这样。
int转byte[]
我们知道了int转byte的方法,那么转byte[]其实就是把4个8位分别放入到4个字节中。
举个例子,1154的二进制为以下。
00000000 00000000 00000100 10000010
而现在有四个byte,也就是byte[4]。
第一个byte为00000000,最终值为0
第二个byte为00000000,最终值为0
第三个byte为00000100,最终值为4
第四个byte为10000010,最终值为-126(最高位为1,为负数,数值部分取反+1)
那么我们来测试一下,是不是这样
public static void main(String[] args) {
ByteBuffer byteBuffer=ByteBuffer.allocate(4);
byteBuffer.putInt(1154);
byteBuffer.flip();
byte[] dst =new byte[4];
byteBuffer.get(dst);
for (byte b : dst) {
System.out.println(b);
}
}
输出结果
byte[]转int
在举个例子,现在byte[4]中的值分别是以下值
byte[0]= 0
byte[1]= 21
byte[2]=-12
byte[3]=-89
+21的补码00010101。
-12的补码11110100.
-89的补码10100111.
最终二进制为00000000 00010101(+21) 11110100(-12) 10100111(-89),为1438887
再来验证一下。
public static void main(String[] args) {
byte[]dst= new byte[]{0,21,-12,-89};
ByteBuffer byteBuffer=ByteBuffer.wrap(dst);
System.out.println(byteBuffer.getInt());
}
输出
在举个负数例子.
byte[0]= -78
byte[1]= 0
byte[2]=0
byte[3]=46
-78的补码为10110010。
+46的补码为00101110。
最终10110010000000000000000000101110,由于最高位是1,是个负数,则将后面的数值取反+1为11001101111111111111111111010010,转换成十进制就是-1308622802。
验证。
public static void main(String[] args) {
byte[]dst= new byte[]{-78,0,0,46};
ByteBuffer byteBuffer=ByteBuffer.wrap(dst);
System.out.println(byteBuffer.getInt());
}
输出
如有错误,请指出