魔数这个词在不同领域代表不同的含义。在计算机领域,魔数有两个含义,一指用来判断文件类型的魔数(magic number);二指程序代码中的魔数,也称魔法值。
不是所有文件都有文件头的。一个.txt类型的文件是一个纯文本文件,没有文件头。
参考文章:
项目中接到魔数校验的需求,这篇文章(Java 通过魔数判断上传文件的类型)对我理解很有帮助,在此基础上,我重新写了工具类的处理,通过文件路径或者文件流获取文件类型(文件类型与对应的文件魔数枚举类),然后通过 FileTypeEnum枚举类的数据再去根据需求处理不同的文件业务。
1、 新建 FileTypeEnum类:文件类型与对应的文件魔数枚举类
import org.apache.commons.lang3.StringUtils;
/**
* 文件类型与对应的文件魔数枚举类
*/
public enum FileTypeEnum {
/**
* JPEG (jpg)
*/
JPEG("JPG", "FFD8FF"),
/**
* PNG
*/
PNG("PNG", "89504E47"),
/**
* GIF
*/
GIF("GIF", "47494638"),
/**
* TIFF (tif)
*/
TIFF("TIF", "49492A00"),
/**
* Windows bitmap (bmp)
*/
BMP("BMP", "424D"),
BMP_16("BMP", "424D228C010000000000"), //16色位图(bmp)
BMP_24("BMP", "424D8240090000000000"), //24位位图(bmp)
BMP_256("BMP", "424D8E1B030000000000"), //256色位图(bmp)
/**
* CAD (dwg)
*/
DWG("DWG", "41433130"),
/**
* Adobe photoshop (psd)
*/
PSD("PSD", "38425053"),
/**
* Rich Text Format (rtf)
*/
RTF("RTF", "7B5C727466"),
/**
* XML
*/
XML("XML", "3C3F786D6C"),
/**
* HTML (html)
*/
HTML("HTML", "68746D6C3E"),
/**
* Email [thorough only] (eml)
*/
EML("EML", "44656C69766572792D646174653A"),
/**
* Outlook Express (dbx)
*/
DBX("DBX", "CFAD12FEC5FD746F "),
/**
* Outlook (pst)
*/
PST("", "2142444E"),
/**
* doc;xls;dot;ppt;xla;ppa;pps;pot;msi;sdw;db
*/
OLE2("OLE2", "0xD0CF11E0A1B11AE1"),
/**
* Microsoft Word/Excel 注意:word 和 excel的文件头一样
*/
XLS("XLS", "D0CF11E0"),
/**
* Microsoft Word/Excel 注意:word 和 excel的文件头一样
*/
DOC("DOC", "D0CF11E0"),
/**
* Microsoft Word/Excel 2007以上版本文件 注意:word 和 excel的文件头一样
*/
DOCX("DOCX", "504B0304"),
/**
* Microsoft Word/Excel 2007以上版本文件 注意:word 和 excel的文件头一样 504B030414000600080000002100
*/
XLSX("XLSX", "504B0304"),
/**
* Microsoft Access (mdb)
*/
MDB("MDB", "5374616E64617264204A"),
/**
* Word Perfect (wpd)
*/
WPB("WPB", "FF575043"),
/**
* Postscript
*/
EPS("EPS", "252150532D41646F6265"),
/**
* Postscript
*/
PS("PS", "252150532D41646F6265"),
/**
* Adobe Acrobat (pdf)
*/
PDF("PDF", "255044462D312E"),
/**
* Quicken (qdf)
*/
QDF("qdf", "AC9EBD8F"),
/**
* QuickBooks Backup (qdb)
*/
QDB("qbb", "458600000600"),
/**
* Windows Password (pwl)
*/
PWL("PWL", "E3828596"),
/**
* ZIP Archive
*/
ZIP("", "504B0304"),
/**
* ARAR Archive
*/
RAR("", "52617221"),
/**
* WAVE (wav)
*/
WAV("WAV", "57415645"),
/**
* AVI
*/
AVI("AVI", "41564920"),
/**
* Real Audio (ram)
*/
RAM("RAM", "2E7261FD"),
/**
* Real Media (rm) rmvb/rm相同
*/
RM("RM", "2E524D46"),
/**
* Real Media (rm) rmvb/rm相同
*/
RMVB("RMVB", "2E524D46000000120001"),
/**
* MPEG (mpg)
*/
MPG("MPG", "000001BA"),
/**
* Quicktime (mov)
*/
MOV("MOV", "6D6F6F76"),
/**
* Windows Media (asf)
*/
ASF("ASF", "3026B2758E66CF11"),
/**
* ARJ Archive
*/
ARJ("ARJ", "60EA"),
/**
* MIDI (mid)
*/
MID("MID", "4D546864"),
/**
* MP4
*/
MP4("MP4", "00000020667479706D70"),
/**
* MP3
*/
MP3("MP3", "49443303000000002176"),
/**
* FLV
*/
FLV("FLV", "464C5601050000000900"),
/**
* 1F8B0800000000000000
*/
GZ("GZ", "1F8B08"),
/**
* CSS
*/
CSS("CSS", "48544D4C207B0D0A0942"),
/**
* JS
*/
JS("JS", "696B2E71623D696B2E71"),
/**
* Visio
*/
VSD("VSD", "d0cf11e0a1b11ae10000"),
/**
* WPS文字wps、表格et、演示dps都是一样的
*/
WPS("WPS", "d0cf11e0a1b11ae10000"),
/**
* torrent
*/
TORRENT("TORRENT", "6431303A637265617465"),
/**
* JSP Archive
*/
JSP("JSP", "3C2540207061676520"),
/**
* JAVA Archive
*/
JAVA("JAVA", "7061636B61676520"),
/**
* CLASS Archive
*/
CLASS("CLASS", "CAFEBABE0000002E00"),
/**
* JAR Archive
*/
JAR("JAR", "504B03040A000000"),
/**
* MF Archive
*/
MF("MF", "4D616E69666573742D56"),
/**
* EXE Archive
*/
EXE("EXE", "4D5A9000030000000400"),
/**
* ELF Executable
*/
ELF("ELF", "7F454C4601010100"),
/**
* Lotus 123 v1
*/
WK1("WK1", "2000604060"),
/**
* Lotus 123 v3
*/
WK3("WK3", "00001A0000100400"),
/**
* Lotus 123 v5
*/
WK4("WK4", "00001A0002100400"),
/**
* Lotus WordPro v9
*/
LWP("LWP", "576F726450726F"),
/**
* Sage(sly.or.srt.or.slt;sly;srt;slt)
*/
SLY("SLY", "53520100"),
/**
* CHM Archive
*/
/* CHM("CHM", "49545346030000006000"),
INI("INI", "235468697320636F6E66"),
SQL("SQL", "494E5345525420494E54"),
BAT("BAT", "406563686F206f66660D"),
PROPERTIES("", "6C6F67346A2E726F6F74"),
MXP("", "04000000010000001300"), */
NOT_EXITS_ENUM("", "");
/**
* 文件类型对应的名称
*/
private String fileTypeName;
/**
* 文件类型对应的魔数
*/
private String magicNumberCode;
private FileTypeEnum(String fileTypeName, String magicNumberCode) {
this.fileTypeName = fileTypeName;
this.magicNumberCode = magicNumberCode;
}
public String getFileTypeName() {
return fileTypeName;
}
public String getMagicNumberCode() {
return magicNumberCode;
}
/**
* 根据文件类型获取文件类型魔数编码
* 默认返回标准件
*
* @param magicNumberCode - 文件类型魔数编码
* @return
*/
public static FileTypeEnum getByMagicNumberCode(String magicNumberCode) {
if (StringUtils.isNotBlank(magicNumberCode)) {
for (FileTypeEnum type : values()) {
if (magicNumberCode.toUpperCase().startsWith(type.getMagicNumberCode())) {
return type;
}
}
}
return FileTypeEnum.NOT_EXITS_ENUM;
}
/**
* 根据文件类型后缀名获取枚举
*
* @param fileTypeName - 文件类型后缀名
* @return
*/
public static FileTypeEnum getByFileTypeName(String fileTypeName) {
if (StringUtils.isNotBlank(fileTypeName)) {
for (FileTypeEnum type : values()) {
if (type.getFileTypeName().equals(fileTypeName)) {
return type;
}
}
}
return FileTypeEnum.NOT_EXITS_ENUM;
}
}
2、新建 FileTypeUtil工具类 测试
import cn.jq.javademo.utils.pojo.FileTypeEnum;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* 文件类型与对应的文件魔数处理工具类
*/
public class FileTypeUtil {
public static void main(String[] args) throws Exception {
File fromPic = new File("D:\\E\\电脑壁纸\\JD导入.xlsx");
FileTypeEnum fileTypeEnum = FileTypeUtil.getFileTypeByInputStream(new FileInputStream(fromPic));
System.out.println(fileTypeEnum.getFileTypeName());
System.out.println(fileTypeEnum.getMagicNumberCode());
System.out.println(fileTypeEnum);
FileTypeEnum fileTypeEnum2 = FileTypeUtil.getFileTypeByPath("D:\\E\\电脑壁纸\\598a80e12f9ad.jpg");
System.out.println(fileTypeEnum2.getFileTypeName());
System.out.println(fileTypeEnum2.getMagicNumberCode());
System.out.println(fileTypeEnum2);
}
/**
* 通过文件路径获取文件类型
* @param path
* @return FileTypeEnum - 文件类型与对应的文件魔数枚举类
*/
public static FileTypeEnum getFileTypeByPath(String path) {
// 获取文件头
String magicNumberCode = magicNumberCode = getFileHeaderHexByPath(path);
if (StringUtils.isNotBlank(magicNumberCode)) {
return FileTypeEnum.getByMagicNumberCode(magicNumberCode.toUpperCase());
}
return FileTypeEnum.NOT_EXITS_ENUM;
}
/**
* 通过文件流获取文件类型
* @param inputStream
* @return FileTypeEnum - 文件类型与对应的文件魔数枚举类
*/
public static FileTypeEnum getFileTypeByInputStream(InputStream inputStream) {
// 获取文件头
String magicNumberCode = getFileHeaderHexByInputStream(inputStream);
if (StringUtils.isNotBlank(magicNumberCode)) {
return FileTypeEnum.getByMagicNumberCode(magicNumberCode.toUpperCase());
}
return FileTypeEnum.NOT_EXITS_ENUM;
}
/**
* 获取文件头(即文件魔数),根据文件路径
* @param path
* @return fileHeaderHex - 文件头,即文件魔数
*/
public static String getFileHeaderHexByPath(String path){
byte[] b = new byte[28];
InputStream inputStream = null;
try {
inputStream = new FileInputStream(path);
inputStream.read(b, 0, 28);
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return bytesToHexString(b);
}
/**
* 获取文件头(即文件魔数),根据通过文件流
* @param inputStream
* @return fileHeaderHex - 文件头,即文件魔数
*/
public static String getFileHeaderHexByInputStream(InputStream inputStream) {
byte[] b = new byte[28];
try {
inputStream.read(b, 0, 28);
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return bytesToHexString(b);
}
/**
* 将文件二进制流(即字节数组)转换成16进制字符串数据
* @param b
* @return fileHeaderHex - 文件头,即文件魔数
*/
private final static String bytesToHexString(byte[] b) {
StringBuilder stringBuilder = new StringBuilder();
if (b == null || b.length <= 0) {
return null;
}
for (int i = 0; i < b.length; i++) {
int v = b[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
}
—— Stay Hungry. Stay Foolish. 求知若饥,虚心若愚。