java利用16进制来辨别png格式的图片
很多人知道利用.png的字符串结尾可以判断前端传入的图片是否为png格式,但是这只是潜意识的判断!那么如何利用png读写的特殊内容来深意识地判断图片格式呢?最近在做东西的时候遇到了点问题,在加载图片的时候,加载失败,后缀都是jpg格式,但换个图片就可以了,为此,怀疑图片格式有问题,遂拖到UE里面查看 它的16进制,果然,两个图片的文件头根本就不一样,这不是欺负人嘛,害我白白浪费了半天的时间,差点要重新编译内核。
然后到网上找了一些资料,查看不同格式图片的文件头是怎样的。下面是不同图片的文件头标志:
图片的格式很多,一个图片文件的后缀名并不能说明这个图片的真正格式什么,那么如何获取图片的格式呢?我想到了几个简单但有效的方法,那就是读取图片文件的文件头标识。我们知道各种格式的图片的文件头标识识不同的,因此我们可以通过判断文件头的标识来识别图片格式。
我对各种格式的图片文件头标识进行了分析,不仅查找资料,也用十六进制编辑器察看过图片的文件头,以下是我收集、分析的结果,供大家参考。
1.JPEG/JPG
- 文件头标识 (2 bytes): $ff, $d8 (SOI) (JPEG 文件标识)
- 文件结束标识 (2 bytes): $ff, $d9 (EOI)
2.TGA
- 未压缩的前5字节 00 00 02 00 00
- RLE压缩的前5字节 00 00 10 00 00
3.PNG
- 文件头标识 (8 bytes) 89 50 4E 47 0D 0A 1A 0A
4.GIF
- 文件头标识 (6 bytes) 47 49 46 38 39(37) 61
G I F 8 9 (7) a
5.BMP
- 文件头标识 (2 bytes) 42 4D
B M
6.PCX
- 文件头标识 (1 bytes) 0A
7.TIFF
- 文件头标识 (2 bytes) 4D 4D 或 49 49
8.ICO
- 文件头标识 (8 bytes) 00 00 01 00 01 00 20 20
9.CUR
- 文件头标识 (8 bytes) 00 00 02 00 01 00 20 20
10.IFF
- 文件头标识 (4 bytes) 46 4F 52 4D
F O R M
11.ANI
- 文件头标识 (4 bytes) 52 49 46 46
R I F F
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException; /**
* 图片转成十六进制
*/
public class img{
public static void main(String[] args) throws Exception {
try{
FileInputStream fis = new FileInputStream("png1.png");
java.io.ByteArrayOutputStream bos=new java.io.ByteArrayOutputStream();
byte[] buff=new byte[1024];
int len=0;
while((len=fis.read(buff))!=-1){
bos.write(buff,0,len);
}
//得到图片的字节数组
byte[] result=bos.toByteArray();
System.out.println("++++"+byte2HexStr(result));
//字节数组转成十六进制
String str=byte2HexStr(result);
}catch(IOException e){
} }
/*
* 实现字节数组向十六进制的转换方法一
*/
public static String byte2HexStr(byte[] b) {
String hs="";
String stmp="";
for (int n=0;n<9;n++) {
stmp=(Integer.toHexString(b[n] & 0XFF));
if (stmp.length()==1) hs=hs+"0"+stmp;
else hs=hs+stmp;
}
return hs.toUpperCase();
}
}
根据这些文件头标识的收集,我可以写一个识别图像格式的模块了。但是在写这个模块之前可以对收集到的文件头标识进行优化,使得程序中字符串比对次数尽量的少。
1.JPEG我们知需要比对文件头的$ff, $d8这两个字符,而不用读取最后的两个结束标识了。
2.TGA,ICO,CUR只需比对第三个与第五个字符即可。
3.PNG比对[89][50]这两个字符。
4.GIF比对[47][49][46]与第五个字符。
废话不多说了,利用内存流来判断文件的格式,其实判断文件的前几个字节就可以简单的判断这个文件是什么类型的文件,例如
jpg文件 是 FFD8 (从低位到高位就要反过来 D8FF 下面都是一样)
BMP文件 是 424D ---4D42
其他的我就不一一列举了,想知道跟多文件类型分别是用什么字符作为文件的开头的话,下载个C32asm或者UE等这类16进制编辑器就可以看到了。
java利用16进制来辨别png格式的图片的更多相关文章
- java中16进制转换10进制
java中16进制转换10进制 public static void main(String[] args) { String str = "04e1"; String myStr ...
- java byte 16进制转换
整型转16进制: int devIdInt = Integer.parseInt(devId);String devIdString = Integer.toHexString(devIdInt); ...
- Java Hex 16进制的 byte String 转换类
package mobi.dzs.android.util; import java.util.Locale; /** * 16进制值与String/Byte之间的转换 * @author Jerry ...
- Java中将16进制字符串转换成汉字
技术交流群:233513714 /** * 将16进制字符串转换成汉字 * @param str * @return */ public static String deUnicode(String ...
- java中 16进制字符串 与普通字符串 与 byte数组 之间的转化
方法依赖commons-codec包 maven的引入方式如下 <dependency> <groupId>commons-codec</groupId> < ...
- Java中16进制与字符串之间的相互转换
笔者前几日在开服过程中需要将字符串转化成为16进制的字符串,在网上找到了一些方法尝试之后,均发现存在一个问题-->字符串转为16进制后再转回来,英文正常,中文出现乱码 经过考虑决定通过以下方式进 ...
- Java 基础------16进制转2进制
我们知道,数字8用二进制表示为:1000 用16进制表示为:8 那么我给你一个16进制的数字,0x7f,他的二进制是什么呢? 一个16进制的位数,用4位表示.比如,0x 7 f 其中: 7用4位二进制 ...
- LR编写Socket脚本方法1(XML/16进制报文data.ws格式)
本文主要讲述了Socket协议脚本的基础知识和编写方法,让大家能够在短时间内快速掌握简单的Socket协议脚本的编写方法.1.socket协议介绍Socket协议有万能协议之称,很多系统底层都是用的s ...
- Java中byte与16进制字符串的互换原理
我们都知道Java中的byte是由8个bit组成的,而16进制即16中状态,它是由4个bit来表示的,因为24=16.所以我们可以把一个byte转换成两个用16进制字符,即把高4位和低4位转换成相应的 ...
随机推荐
- Python全栈--7模块--random os sys time datetime hashlib pickle json requests xml
模块分为三种: 自定义模块 内置模块 开源模块 一.安装第三方模块 # python 安装第三方模块 # 加入环境变量 : 右键计算机---属性---高级设置---环境变量---path--分号+py ...
- extjs,清空treepanel数据。
extjs,清空treepanel数据. //调用 var rootNode = tree.getRootNode(); removeChildrenData(rootNode); //清理节点的数据 ...
- mysql时间查看以及定时器相关操作
1.查看事件 show events select * from mysql.event 2.查看是否开启定时器 0:off:1:on 开启定时器:set global event_scheduler ...
- SQL Server 判定时间是否在某个时间区间内
* FROM sys.objects WHERE name=N'uF_IsRange_Date' AND [type]='FN') DROP FUNCTION uF_IsRange_Date GO S ...
- const限定符
1 const的作用 便于进行类型检查.可以保护被修饰的东西.避免不必要的内存分配.为函数重载提供一个参考. 2 const成员函数 const成员函数只能访问数据成员的值,而不能修改他. #incl ...
- iOS富文本的使用
NSString *name = nil; if (_payNumber == 1) { name = [NSString stringWithFormat:@"向%@收款",na ...
- linux 清理内存命令 查看内存命令
查看内存: 我们可以用free命令查看内存信息: free -g total used free shared buffers cachedMem: 15 15 0 0 ...
- 转自知乎:GitHub基本功能
作者:Fadeoc Khaos 链接:https://www.zhihu.com/question/20070065 来源:知乎 著作权归作者所有Github的基本功能: Repository:你和我 ...
- [Chapter 3 Process]Practice 3.4 Describe what happens when a context switch occurs if the new context is already loaded into one of the register sets.
3.4 The Sun UltraSPARC processor has multiple register sets. Describe what happens when a context sw ...
- Replace Pioneer 续用2
软件介绍(摘自百度百科) Replace Pioneer(中文名:替换先锋)是Mind Pioneer出品的一款共享软件. Replace Pioneer是一款与众不同的专业文本批量替换和处理软 ...