DataInputStream类readLong()引起的思考
今天无意中看了下jdk中的DataInputStream类,然后看到readLong()方法,如下:
private byte readBuffer[] = new byte[8];
public final long readLong() throws IOException {
readFully(readBuffer, 0, 8);
return (((long)readBuffer[0] << 56) +
((long)(readBuffer[1] & 255) << 48) +
((long)(readBuffer[2] & 255) << 40) +
((long)(readBuffer[3] & 255) << 32) +
((long)(readBuffer[4] & 255) << 24) +
((readBuffer[5] & 255) << 16) +
((readBuffer[6] & 255) << 8) +
((readBuffer[7] & 255) << 0));
}
顿时觉得很困惑,为什么数组里的第一个元素直接进行移位运算,而后面的都和255进行了与运算呢?
当时觉得困惑的原因是因为byte类型转成int类型应该不用做任何处理的,后来查了下资料后获得了灵感,找到了原因。
原因是这样的,在将输入流的内容读取到byte数组时,会进行截断。因为输入流读取时,虽然是按byte读取的,但是是以int类型返回,且数据范围是1~255,除非到了输入流结束时,返回才是-1。所以在将数据读取到byte数组,不可避免会进行截断,对于一般的数据可能没有问题,但是对于255这样高位以1开头的数据,会有问题。因为java都是有符号数,开头为1代表是负数。这样,在readLong()里,对数据元素进行移位时,会默认转换成int型,这样就导致byte型的255转成int型后,高位依旧为1(实际上代表的是-1了)。这样并不是我们想要的。实际上需要对这些元素进行无符号扩展,也就是高位补0。这就是为什么都要和255做与运算的原因。同样,可以考虑下为什么第一个元素没有进行与运算直接就移位了?其实答案很简单,就是因为在左移动56位后,高位的8位数字必然是数组里的第一个元素。
通过这个,我们其实可以做一些无符号左移的操作。
byte[] bytes = new byte[] { (byte) -42 };
ByteArrayInputStream input = new ByteArrayInputStream(bytes);
int i = input.read();
System.out.println("无符号数:" + i);
System.out.println("无符号二进制数:" + Integer.toBinaryString(i));
另外可以用更简单的方式:
byte b = (byte) -42;
int result = (b & 0xFF);
System.out.println("无符号数:" + result);
System.out.println("无符号二进制数:" + Integer.toBinaryString(result));
这种方式就用到上面提到的与计算方式。
DataInputStream类readLong()引起的思考的更多相关文章
- DataInputStream类和RandomAccessFile类的使用方法
// DataInputStream类实现了DataInput接口,要想从文件中读入二进制数据, // 你需要将DataInputStream与某个字节源相结合,例如FileInputStream / ...
- 20180805-Java DataInputStream类
DataInputStream dis = DataInputStream(InputStream in); 下面的例子演示了DataInputStream和DataOutputStream的使用,该 ...
- Java基础:浅谈数据输入流/数据输出流《DataInputstream类与DataOutputstream类》
一.理论概述 数据输入/输出流(DataInputStream类与DataOutputStream类) 允许应用程序以与机器无关的方式从底层输入流中读取基本Java数据类型. 说白了就是,当读取一个 ...
- 关于Emit中动态类型TypeBuilder创建类标记的一点思考
利用TypeBuilder是可以动态创建一个类型,现在有个需求,动态生成一个dll,创建类型EmployeeEx,需要继承原dll里面的Employee类,并包含Employee类上的所有类标记. ...
- 数据操作流DataOutputStream、DataInputStream类
[例子1] import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import ...
- 前端框架中 “类mixin” 模式的思考
"类 mixin" 指的是 Vue 中的 mixin,Regular 中的 implement 使用 Mixin 的目的 首先我们需要知道为什么会有 mixin 的存在? 为了扩展 ...
- 关于Java构造类与对象的思考
简单记录一下Java构造类与对象时的流程以及this和super对于特殊例子的分析. 首先,接着昨天的问题,我做出了几个变形: Pic1.原版: Pic2.去掉了T.foo方法中的this关键字: P ...
- c# 对 struct为什么不能继承类和结构的思考
1.类.结构在使用的时候可以不调用构造函数,如果能够继承类,这种情况下不能够初始化基类,因为不执行构造函数 2.结构.所有的结构类型都默认是 sealed,通过 反汇编可以看到 ,这就阻止了结构被继 ...
- Python - 关于类(self/cls) 以及 多进程通讯的思考
Python-多进程中关于类以及类实例的一些思考 目录 Python-多进程中关于类以及类实例的一些思考 1. 背景 2. Python 类中的函数 - staticmethod / classmet ...
随机推荐
- 关于Smartforms换页的
smartforms中有系统变量SFSY-PAGE是总页码,SFSY-FORMPAGES是当前页,可以最后的窗体中做个判断 1.把窗体设置成最终窗体 2.新增一个命令,当前页等于最后一页才输出改内容, ...
- 新秀操作和维护注意事项:Windows关于使用Xshell管理你的云主机
假设你PC它是linux系统.那么直接与终端ssh命令就可以了.假设Windows系统.使用它是必要的sshclient. PS:我双系统. 有时候,他们想使用Windows的. Windows上ss ...
- Linux通配符摘要
参考<鸟哥linux私房菜> * - 通配符,代表随机字符(0对于许多) ? - 通配符,它代表一个字符 # - 凝视 / - 跳转符号,将特殊字符或通配符还原成一般符号 | - 分隔两个 ...
- win 7 设置防火墙例外的端口号, 让其域网中可以访问
背景,发布 一个tomcat下的website, 而发局域网可以访问. 这时,可以关闭防火墙:或者开启防火墙,并设置一个防火墙的入站规则,让身边的同事访问这个website. 设置方法:win 7 - ...
- java中synchronized的使用方法与具体解释
Java语言的keyword.当它用来修饰一个方法或者一个代码块的时候,可以保证在同一时刻最多仅仅有一个线程运行该段代码. 一.当两个并发线程訪问同一个对象object中的这个synchronized ...
- Android平均分布的布局图像的下一行
Android下一行平均分布图片的布局 这是一个非经常见的需求,比方有三个图片button,须要在底部三个平均,比方下个样例: 下面是布局文件 <LinearLayout android:lay ...
- 简体中文 — ANSI Common Lisp 中文版
简体中文 - ANSI Common Lisp 中文版 简体中文¶
- Delphi Windows API判断文件共享锁定状态(使用OpenFile来判断)
一.概述 锁是操作系统为实现数据共享而提供的一种安全机制,它使得不同的应用程序,不同的计算机之间可以安全有效地共享和交换数据.要保证安全有效地操作共享数据,必须在相应的操作前判断锁的类型,然后才能确定 ...
- Android本地视频播放器开发--简易播放器原型
在以前的基础上,将音视频进行合并,音频播放采用OpenSL ES,视频播放采用OpenGL ES2.0进行显示,这次的版本其中音频和视频是在同一个线程,会造成音频断断续续,后续会采用音频使用SDL,视 ...
- Tiny server:小型Web服务器
一.背景 csapp的网络编程粗略的介绍了关于网络编程的一些知识,在最后的一节主要就实现了一个小型的Webserver.这个server名叫Tiny,它是一个小型的可是功能齐全的Webserver.在 ...