开发笔记之:文件读取值溢出bug分析(JAVA版)

文章讨论了一段Java代码在使用FileInputStream读取数据文件时遇到的溢出问题,特别是在处理大值时。解决方案包括将数组元素类型由int扩展为long或在返回语句中进行类型转换。强调了在处理可能超出int范围的数据时应选择更大的数据类型,以避免值溢出。
摘要由CSDN通过智能技术生成
(1)引言

 以下是Java读取数据文件(FileInputStream)的代码:

	/**
	 * 按双字读取
	 * @param fis						文件输入流
	 * @param isBigEndian				是否大头(字节序)
	 * @return				双字值 | <code>-1</code>表示EOF
	 */
	public long readAsDword(FileInputStream fis, boolean isBigEndian) {
		int[] bytes = new int[] { -1, -1, -1, -1 };
		try {
			bytes[0] = fis.read();
			bytes[1] = fis.read();
			bytes[2] = fis.read();
			bytes[3] = fis.read();
		} catch (IOException e) {
			。。。
		}
		//EoF checking
		if((-1 == bytes[3])||(-1 == bytes[2])||(-1 == bytes[1])||(-1 == bytes[0])) {
			return (-1);
		}
		if(isBigEndian) { //big-endian: 00 01 02 03
			return ((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]);
		} else { //little-endian: 03 02 01 00
			return ((bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0]);
		}
	}

 其意图很简单:从当前游标位置读取一个双字(4字节)数据。
稍微复杂一点的就是一个字节序的考虑。

(2)问题

 该代码做UT(单元测试)时,遇到了读取中断的问题(就是文件还没读取完就提前中断了)。以下是数据文件内容:
数据文件sample中断的原因就是返回值为约定的 -1
经调试跟踪,在读取第1个 0xFFFFFF 时,每个字节的读取都正常(255 < Integer.MAX_VALUE),问题发生在代码的 return 语句处,返回 -1值了:

return ((bytes[0] << 24)|(bytes[1] << 16)|(bytes[2] << 8)|bytes[3]);

也就是说,发生了值溢出
原因也立刻明了:数组bytes的元素的类型为int,当赋值 0xFFFFFF (>Integer.MAX_VALUE) 时产生溢出。

(2.1)对策
  1. 在return语句处,将bytes的元素的值强制扩展为long,如下:
return (((long)bytes[0] << 24)|((long)bytes[1] << 16)|((long)bytes[2] << 8)|(long)bytes[3]);
  1. 将数组bytes的元素的类型扩展为long也可。如下:
long[] temp = new long[] { -1L, -1L, -1L, -1L };
(3)结论

数据文件读取溢出需关注的点:

  1. 目标的值域范围(宁大勿小,例如:能用long就不要用int)
  2. 数值计算过程中的值溢出
(4)相关文档
  1. 开发笔记之:文件读取值溢出bug分析(QT C++版)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值