与Java的class文件类似,很多类型的文件,起始的几个字节内容都是固定的,跟据这几个字节的内容,就可以判断文件的类型,这几个字节也被称为“魔数”,比如class文件的魔数就是“CAFEBABE”。
通过魔数判断文件类型便是一种更安全的方式:
一:创建枚举类
public enum FileType {
/** JPEG */
JPEG("FFD8FF"),
/** PNG */
PNG("89504E47"),
/** GIF */
GIF("47494638"),
/** TIFF */
TIFF("49492A00"),
/** Windows bitmap */
BMP("424D"),
/** CAD */
DWG("41433130"),
/** Adobe photoshop */
PSD("38425053"),
/** Rich Text Format */
RTF("7B5C727466"),
/** XML */
XML("3C3F786D6C"),
/** HTML */
HTML("68746D6C3E"),
/** Outlook Express */
DBX("CFAD12FEC5FD746F "),
/** Outlook */
PST("2142444E"),
/** doc;xls;dot;ppt;xla;ppa;pps;pot;msi;sdw;db */
OLE2("0xD0CF11E0A1B11AE1"),
/** Microsoft Word/Excel */
XLS_DOC("D0CF11E0"),
/** Microsoft Access */
MDB("5374616E64617264204A"),
/** Word Perfect */
WPB("FF575043"),
/** Postscript */
EPS_PS("252150532D41646F6265"),
/** Adobe Acrobat */
PDF("255044462D312E"),
/** Windows Password */
PWL("E3828596"),
/** ZIP Archive */
ZIP("504B0304"),
/** ARAR Archive */
RAR("52617221"),
/** WAVE */
WAV("57415645"),
/** AVI */
AVI("41564920"),
/** Real Audio */
RAM("2E7261FD"),
/** Real Media */
RM("2E524D46"),
/** Quicktime */
MOV("6D6F6F76"),
/** Windows Media */
ASF("3026B2758E66CF11"),
/** MIDI */
MID("4D546864");
private String value = "";
private FileType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
二:创建工具类
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class FilUtil {
public static FileType getType(String filePath) throws IOException {
// 获取文件头
String fileHead = getFileHeader(filePath);
if (fileHead != null && fileHead.length() > 0) {
fileHead = fileHead.toUpperCase();
FileType[] fileTypes = FileType.values();
for (FileType type : fileTypes) {
if (fileHead.startsWith(type.getValue())) {
return type;
}
}
}
return null;
}
/** 读取文件头 */
private static String getFileHeader(String filePath) throws IOException {
byte[] b = new byte[28];
InputStream inputStream = null;
try {
inputStream = new FileInputStream(filePath);
inputStream.read(b, 0, 28);
} finally {
if (inputStream != null) {
inputStream.close();
}
}
return bytesToHex(b);
}
/** 将字节数组转换成16进制字符串 */
public static String bytesToHex(byte[] src){
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
}
需要注意的是,可能存在一种类型文件的魔数与另一种类型文件魔数的前面部分相等(如‘D0CF11E0’与‘D0CF11E0A1B11AE1’),所以应该尽量将更长的魔数值放在上面。这里的文件与魔数枚举得也不全面,但思路就这样。
以下例出的是一些我们常见的文件类型,以及它用于判断这种文件的类型的几个开始字节及所对尖的ASCII数字:
图片文件
文件类型 | 扩展名 | 16进制数字 xx这里表示变量 | Ascii数字 . = 不是Ascii字符 |
---|---|---|---|
Bitmap format | .bmp | 42 4d | BM |
FITS format | .fits | 53 49 4d 50 4c 45 | SIMPLE |
GIF format | .gif | 47 49 46 38 | GIF8 |
Graphics Kernel System | .gks | 47 4b 53 4d | GKSM |
IRIS rgb format | .rgb | 01 da | .. |
ITC (CMU WM) format | .itc | f1 00 40 bb | …. |
JPEG File Interchange Format | .jpg | ff d8 ff e0 | …. |
NIFF (Navy TIFF) | .nif | 49 49 4e 31 | IIN1 |
PM format | .pm | 56 49 45 57 | VIEW |
PNG format | .png | 89 50 4e 47 | .PNG |
Postscript format | .[e]ps | 25 21 | %! |
Sun Rasterfile | .ras | 59 a6 6a 95 | Y.j. |
Targa format | .tga | xx xx xx | … |
TIFF format (Motorola – big endian) | .tif | 4d 4d 00 2a | MM.* |
TIFF format (Intel – little endian) | .tif | 49 49 2a 00 | II*. |
X11 Bitmap format | .xbm | xx xx | |
XCF Gimp file structure | .xcf | 67 69 6d 70 20 78 63 66 20 76 | gimp xcf |
Xfig format | .fig | 23 46 49 47 | #FIG |
XPM format | .xpm | 2f 2a 20 58 50 4d 20 2a 2f | /* XPM */ |
压缩文件
文件类型 | 扩展名 | 16进制数字 xx这里表示变量 | Ascii数字 . = 不是Ascii字符 |
---|---|---|---|
Bzip | .bz | 42 5a | BZ |
Compress | .Z | 1f 9d | .. |
gzip format | .gz | 1f 8b | .. |
pkzip format | .zip | 50 4b 03 04 | PK.. |
存档文件
文件类型 | 扩展名 | 16进制数字 xx这里表示变量 | Ascii数字 . = 不是Ascii字符 |
---|---|---|---|
TAR (pre-POSIX) | .tar | xx xx | (a filename) |
TAR (POSIX) | .tar | 75 73 74 61 72 | ustar (offset by 257 bytes) |
可执行文件
文件类型 | 扩展名 | 16进制数字 xx这里表示变量 | Ascii数字 . = 不是Ascii字符 |
---|---|---|---|
MS-DOS, OS/2 or MS Windows | 4d 5a | MZ | |
Unix elf | 7f 45 4c 46 | .ELF |
其它文件
文件类型 | 扩展名 | 16进制数字 xx这里表示变量 | Ascii数字 . = 不是Ascii字符 |
---|---|---|---|
pgp public ring | 99 00 | .. | |
pgp security ring | 95 01 | .. | |
pgp security ring | 95 00 | .. | |
pgp encrypted data | a6 00 | ¦. |
除上述“魔数”外,还可以判断图片是否可以缩放,即获取长和宽:
/**
* <p>Discription:[isImage,判断文件是否为图片]</p>
* @param file
* @return true 是 | false 否
*/
public static final boolean isImage(File file){
boolean flag = false;
try
{
BufferedImage bufreader = ImageIO.read(file);
int width = bufreader.getWidth();
int height = bufreader.getHeight();
if(width==0 || height==0){
flag = false;
}else {
flag = true;
}
}
catch (IOException e)
{
flag = false;
}catch (Exception e) {
flag = false;
}
return flag;
}