java:Not a JPEG file: starts with 0xff 0xd9错误引起的一个小问题

今天在写图片验证码的业务时候,需要将base64字符串转换为图片,然后在这个图片上画出对应的矩阵块,完成滑块拼图验证码的实现,一个demo如下。

        String s = fileToBase64("C:\\Users\\Administrator\\Desktop\\微信图片_20230302221300.jpg");
        byte[] decode = Base64.getDecoder().decode(s);
        try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(decode)){
        	// 转化为bufferedImage后期拼图
            BufferedImage read = ImageIO.read(byteArrayInputStream);
            Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("jpg");
            ImageReader reader = (ImageReader) readers.next();
             ImageReadParam defaultReadParam = reader.getDefaultReadParam();
            ImageInputStream iis = ImageIO.createImageInputStream(byteArrayInputStream);
            reader.setInput(iis, true);
            // new ctangle和ImageReadParam 实现矩形框,并写到该图片中
            reader.read(0,defaultReadParam)
        }
        catch (IOException e) {
            e.printStackTrace();
        }

在使用过程中,出现了以下报错:Not a JPEG file: starts with 0xff 0xd9

javax.imageio.IIOException: Not a JPEG file: starts with 0xff 0xd9
	at com.sun.imageio.plugins.jpeg.JPEGImageReader.readImageHeader(Native Method)
	at com.sun.imageio.plugins.jpeg.JPEGImageReader.readNativeHeader(JPEGImageReader.java:628)
	at com.sun.imageio.plugins.jpeg.JPEGImageReader.checkTablesOnly(JPEGImageReader.java:347)
	at com.sun.imageio.plugins.jpeg.JPEGImageReader.gotoImage(JPEGImageReader.java:495)
	at com.sun.imageio.plugins.jpeg.JPEGImageReader.readHeader(JPEGImageReader.java:621)
	at com.sun.imageio.plugins.jpeg.JPEGImageReader.getWidth(JPEGImageReader.java:735)

说这个图片的文件格式头不是标准的jpg,但是通过调试发现base64编码的图片可以被解析,查阅jpg图片格式发现文件头是以0xff 0xd9结尾并非以此开始,细想半天一开始怀疑是不是在base64转图片流的时候是不是搞反了,导致从文件末尾开始读,后来debug发现并没有改动。然后又对ImageReader 一顿输出,结果还是错误。然后偶然的一次尝试,将BufferedImage read = ImageIO.read(byteArrayInputStream)调整至最后一行,奇迹的发现竟然运行通过了,这尼玛……

猜测

一开始以为ImageIO.read在读取文件后导致字节倒叙了,debug一顿然而并没有。

原因

ImageIO.read将byteArrayInputStream流读到了末尾,换言之就是说byteArrayInputStream被消耗了,指针读到了末尾,因为两个图片读取方法操作的一个byteArrayInputStream,所以导致ImageReader读取的是个空的流!可以前后增加:

System.out.println(byteArrayInputStream.available());
BufferedImage read = ImageIO.read(byteArrayInputStream);
System.out.println(byteArrayInputStream.available());

发现第二次打印为0,这就证明了byteArrayInputStream指针指到了末尾,通过:

byteArrayInputStream.reset();

可以将其指到初始位置,从而解决了这个问题。
ImageIO.read源码也是用到了ImageReader,通过源码可以看出至始至终都是在操作byteArrayInputStream并没有copy,ImageReader传入的是ImageInputStream才没有发生该情况。
一致在反复的验证base64是否损失图片格式类型和流的各种子类转换问题了,从而忽视这一个细节。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值