byte与int互转及原理解析

本文详细探讨了在处理BMP图片格式时遇到的字节问题,包括byte和int类型在Java和C#中的存储特性,以及在不同编程语言中字节和整数之间的转换,特别关注了Little-endian和Big-endian模式在数据流读取中的应用。
摘要由CSDN通过智能技术生成

一、背景

在解析微软.bmp图片格式的时候,bmp格式的文件前两个字节是固定的0x424D,后面4个字节是该bmp文件的大小,在使用 DataInputStream.readInt 读取的大小和预期不一致,基于此,整理了研究过程....

二、Byte解析

2.1 Byte理解

byte是字节的意思,一个字节是8位,范围是 0000 0000 ~ 1111 1111(十六进制:0x0~0xff),总共包含256个数。

java里 byte 范围是  -128~127

C#里的byte 范围是  0~255

存储的数据二进制都是一样的,只是每个语言定义的问题,高位是否定义为符号位,其数据自身二进制形式是一样的

计算机存储的是 机器码,存储的值是 原数值的补码,

java里的byte 高位是符号位

正数部分:正数的补码还是自己,即 0000 0000 ~ 0111 1111 表示范围是 [0,127] ,
负数部分:负数的补码 是该数的原码除负号位外各位取反,然后在最后一位加1,即 1111 1111 ~ 1000 0000 对应的原值 1 0000 0000 ~ 1000 0001  即为 [-128,-1]

C#里的byte是无符号数,所以全部是正数,即 0000 0000 ~ 1111 1111 表示范围是 [0,255] 

虽然取值范围不同,但是byte存储的结构还是一致,依然是8位 0000 0000 ~ 1111 1111,通过以下代码验证。

2.2 代码验证
2.2.1 java验证

选取 0,1,127,-1,-128 打印对应的结构,所以可以看出 是有符号的数

查看temp3.txt文件中对应的二进制结构

2.2.2  C#验证

选取 0,1,127,255,128 打印对应的结构,所以可以看出 是无符号的数

查看temp4.txt文件中对应的二进制结构

三、Int解析

int类型有符号的,在内存中占用了4个字节,也就是32位。使用最高位来存储符号,最高位是0表示数据是正数,最高位是1表示数据是负数,使用其他的31位来存储数据,负数依然是存储机器码(补码)

其中 正数前面的0没有显示,但int还是32位,前面的0缺省了

java代码示例

C#代码示例

四、Byte和Int互转

4.1 int转byte原理

示例: -128 转为 byte结构

-128 的二进制 11111111 11111111 11111111 10000000,总共32位,切换为byte数组的话就是8位一组,byte[0] 11111111,byte[1] 11111111 ,byte[2] 11111111 ,byte[3] 10000000

示例:41078转为byte结构

41078 的二进制 00000000 00000000 10100000 01110110,切换为byte数组的话就是8位一组,byte[0] 00000000,byte[1] 00000000,byte[2] 10100000,byte[3] 01110110

注意 上面这个byte切换是 Big-endian模式(内存高位在后面),对应的另一种是 Little-endian

41078的Little-endian模式下 byte数组结构为 byte[0] 01110110,byte[1] 10100000,byte[2] 00000000,byte[3] 00000000,顺序反过来,Windows平台多数为Little-endian,C#语言获取byte数组时候就是 Little-endian模式,看上面的代码输出示例

4.2 byte转int

原理:byte 是8位,int32位,一种是无视高位符号位前面直接补0,另一种是 保留高位符号位中间补0

无视高位直接补0:DataInputStream对象的 dataInputStream.read(),一般在文件流里,读取一个字节返回int

保留高位符号位:byte a =-1;int a4 =a; 这种就是常规的赋值,转化后值不变,存储长度变长

4.3 引申

读取文件流操作里,dataInputStream.readInt() 是读取4个字节以Big-endian模式转化成一个int,另一个可以用 LittleEndian.readInt(inputStream) 以Little-endian模式转化成一个int

//LittleEndian readInt 源码
public static int readInt(InputStream stream) throws IOException, LittleEndian.BufferUnderrunException {
	int ch1 = stream.read();
	int ch2 = stream.read();
	int ch3 = stream.read();
	int ch4 = stream.read();
	if ((ch1 | ch2 | ch3 | ch4) < 0) {
		throw new LittleEndian.BufferUnderrunException();
	} else {
		return (ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0);
	}
}
//DataInputStream readInt 源码
public final int readInt() throws IOException {
	int ch1 = in.read();
	int ch2 = in.read();
	int ch3 = in.read();
	int ch4 = in.read();
	if ((ch1 | ch2 | ch3 | ch4) < 0)
		throw new EOFException();
	return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}

观察上面的代码,根据不同模式,左移不同位数来转化成int

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值