魔數校驗,根據指定文件的文件頭判斷其文件類型

 

不同文件類型的魔術數字,指定是文件的最開頭的幾個用於唯一區別其它文件類型的字節,有了這些魔術數字,我們就可以很方便的區別不同的文件,這也使得編程變得更加容易,因爲我減少了我們用於區別一個文件的文件類型所要花費的時間。

比如,一個JPEG文件,它開頭的一些字節可能是類似這樣的”ffd8 ffe0 0010 4a46 4946 0001 0101 0047 ……JFIF…..G“,這裏”ffd8“就表示了這個文件是一個JPEG類型的文件,”ffe0“表示這是JFIF類型結構。

以下例出的是一些我們常見的文件類型,以及它用於判斷這種文件的類型的幾個開始字節及所對尖的ASCII數字

https://blog.csdn.net/ycb1689/article/details/79712623

/**
	 * 根據制定文件的文件頭判斷其文件類型
	 * 
	 * @param b 文件內容頭
	 * @return
	 */
	public static String getFileType(byte[] b) {
		String res = null;
		String fileCode = bytesToHexString(b);
		// 這種方法在字典的頭代碼不夠位數的時候可以用但是速度相對慢一點
		Iterator<Map.Entry<String, String>> entryIter = FILE_TYPE_MAP.entrySet().iterator();
		while (entryIter.hasNext()) {
			Map.Entry<String, String> entry = entryIter.next();
			if (entry.getKey().toLowerCase().startsWith(fileCode.toLowerCase())
					|| fileCode.toLowerCase().startsWith(entry.getKey().toLowerCase())) {
				res = entry.getValue();
				break;
			}
		}
		return res;
	}

FILE_TYPE_MAP定義配置文件:magicNumber.properties

ffd8ff=jpg
89504e47=png
424d=bmp
47494638=gif
00000020667479706d70=mp4
2e524d46000000120001=rmvb
52494646d07d60074156=avi
4d546864000000060001=mid
49443303000000002176=mp3
52494646e27807005741=wav
d0cf11e0=doc
504b0304140006=docx
255044462d312e=pdf
d0cf11e0a1b11ae10000=vsd
38425053=psd
3c21444f=html
3c21646f=htm
000001ba210001000180=mpg
3026b2758e66cf11a6d9=wmv
41433130=dwg
48544d4c=css
696b2e71=js
7b5c7274=rtf
46726f6d=eml
6D6F6F76=mov
FF575043=wpd
2142444E=pst
AC9EBD8F=qdf
E3828596=pwl
2E7261FD=ram
49492a00=tif
CFAD12FEC5FD746F=dbx
5374616E64617264204A=mdb
252150532D41646F6265=ps
464c5601050000000900=flv
504b030414000=zip
526172211a0700cf9073=rar
504b03040a0000000000=jar
4d616e69666573742d56=mf
3c3f786d6c2076657273=xml
1f8b0800000000000000=gz
49545346030000006000=chm
d0cf11e0a1b11ae10000=wps


package com.stt.common.util;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;

public class FileTypeUtil {
	public final static Map<String, String> FILE_TYPE_MAP = new HashMap<String, String>();
	private static Properties prop = CmUtil.getProps("/magicNumber.properties");
	static String typeWhiteList = CmUtil.getProps("/conf.properties").getProperty("file_type_white_list");

	

	private FileTypeUtil() {
	}

	static { // 初始化文件類型信息
		if(FILE_TYPE_MAP.size() == 0){
			Iterator<Entry<Object, Object>> it= prop.entrySet().iterator();
			while(it.hasNext()){
			    Map.Entry<Object, Object> entry=(Map.Entry<Object, Object>)it.next();
			    String key = String.valueOf(entry.getKey());
			    String value = String.valueOf(entry.getValue());
			    FILE_TYPE_MAP.put(key, value);
			}
		}
		/*FILE_TYPE_MAP.put("ffd8ff", "jpg"); // JPEG (jpg)
		FILE_TYPE_MAP.put("89504e47", "png"); // PNG (png)
		FILE_TYPE_MAP.put("47494638", "gif"); // GIF (gif)
		FILE_TYPE_MAP.put("49492a00", "tif"); // TIFF (tif)
		FILE_TYPE_MAP.put("424d228c", "bmp"); // 16色位圖(bmp)
		FILE_TYPE_MAP.put("424d8240", "bmp"); // 24位位圖(bmp)
		FILE_TYPE_MAP.put("424d8e1b", "bmp"); // 256色位圖(bmp)
		FILE_TYPE_MAP.put("41433130", "dwg"); // CAD (dwg)
		FILE_TYPE_MAP.put("3c21444f", "html"); // HTML (html)
		FILE_TYPE_MAP.put("3c21646f", "htm"); // HTM (htm)
		FILE_TYPE_MAP.put("48544d4c", "css"); // css
		FILE_TYPE_MAP.put("696b2e71", "js"); // js
		FILE_TYPE_MAP.put("7b5c7274", "rtf"); // Rich Text Format (rtf)
		FILE_TYPE_MAP.put("38425053", "psd"); // Photoshop (psd)
		FILE_TYPE_MAP.put("46726f6d", "eml"); // Email [Outlook Express 6] (eml)
		FILE_TYPE_MAP.put("d0cf11e0", "doc"); // MS Excel
		FILE_TYPE_MAP.put("d3a6d3c3", "txt"); // MS Excel
															// 注意:word、msi 和
															// excel的文件頭一樣
		FILE_TYPE_MAP.put("d0cf11e0a1b11ae10000", "vsd"); // Visio 繪圖
		FILE_TYPE_MAP.put("5374616E64617264204A", "mdb"); // MS Access (mdb)
		FILE_TYPE_MAP.put("252150532D41646F6265", "ps");
		FILE_TYPE_MAP.put("255044462d312e350d0a", "pdf"); // Adobe Acrobat (pdf)
		FILE_TYPE_MAP.put("2e524d46000000120001", "rmvb"); // rmvb/rm相同
		FILE_TYPE_MAP.put("464c5601050000000900", "flv"); // flv與f4v相同
		FILE_TYPE_MAP.put("00000020667479706d70", "mp4");
		FILE_TYPE_MAP.put("49443303000000002176", "mp3");
		FILE_TYPE_MAP.put("000001ba210001000180", "mpg"); //
		FILE_TYPE_MAP.put("3026b2758e66cf11a6d9", "wmv"); // wmv與asf相同
		FILE_TYPE_MAP.put("52494646e27807005741", "wav"); // Wave (wav)
		FILE_TYPE_MAP.put("52494646d07d60074156", "avi");
		FILE_TYPE_MAP.put("4d546864000000060001", "mid"); // MIDI (mid)
		FILE_TYPE_MAP.put("504b0304140000000800", "zip");
		FILE_TYPE_MAP.put("526172211a0700cf9073", "rar");
		FILE_TYPE_MAP.put("235468697320636f6e66", "ini");
		FILE_TYPE_MAP.put("504b03040a0000000000", "jar");
		FILE_TYPE_MAP.put("4d5a9000030000000400", "exe");// 可執行文件
		FILE_TYPE_MAP.put("3c25402070616765206c", "jsp");// jsp文件
		FILE_TYPE_MAP.put("4d616e69666573742d56", "mf");// MF文件
		FILE_TYPE_MAP.put("3c3f786d6c2076657273", "xml");// xml文件
		FILE_TYPE_MAP.put("494e5345525420494e54", "sql");// xml文件
		FILE_TYPE_MAP.put("7061636b616765207765", "java");// java文件
		FILE_TYPE_MAP.put("406563686f206f66660d", "bat");// bat文件
		FILE_TYPE_MAP.put("1f8b0800000000000000", "gz");// gz文件
		FILE_TYPE_MAP.put("6c6f67346a2e726f6f74", "properties");// bat文件
		FILE_TYPE_MAP.put("cafebabe0000002e0041", "class");// bat文件
		FILE_TYPE_MAP.put("49545346030000006000", "chm");// bat文件
		FILE_TYPE_MAP.put("04000000010000001300", "mxp");// bat文件
		FILE_TYPE_MAP.put("504b0304140006000800", "docx");// docx文件
		FILE_TYPE_MAP.put("d0cf11e0a1b11ae10000", "wps");// WPS文字wps、表格et、演示dps都是一樣的
		FILE_TYPE_MAP.put("6431303a637265617465", "torrent");
		FILE_TYPE_MAP.put("6D6F6F76", "mov"); // Quicktime (mov)
		FILE_TYPE_MAP.put("FF575043", "wpd"); // WordPerfect (wpd)
		FILE_TYPE_MAP.put("CFAD12FEC5FD746F", "dbx"); // Outlook Express (dbx)
		FILE_TYPE_MAP.put("2142444E", "pst"); // Outlook (pst)
		FILE_TYPE_MAP.put("AC9EBD8F", "qdf"); // Quicken (qdf)
		FILE_TYPE_MAP.put("E3828596", "pwl"); // Windows Password (pwl)
		FILE_TYPE_MAP.put("2E7261FD", "ram"); // Real Audio (ram)
*/	}

	/**
	 * 得到上傳文件的文件頭
	 * 
	 * @param src
	 * @return
	 */
	private static String bytesToHexString(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();
	}

	/**
	 * 根據制定文件的文件頭判斷其文件類型
	 * 
	 * @param b 文件內容頭
	 * @return
	 */
	public static String getFileType(byte[] b) {
		String res = null;
		String fileCode = bytesToHexString(b);
		// 這種方法在字典的頭代碼不夠位數的時候可以用但是速度相對慢一點
		Iterator<Map.Entry<String, String>> entryIter = FILE_TYPE_MAP.entrySet().iterator();
		while (entryIter.hasNext()) {
			Map.Entry<String, String> entry = entryIter.next();
			if (entry.getKey().toLowerCase().startsWith(fileCode.toLowerCase())
					|| fileCode.toLowerCase().startsWith(entry.getKey().toLowerCase())) {
				res = entry.getValue();
				break;
			}
		}
		return res;
	}
	
	public static boolean suffixCheck(String type) {
        if(type == null || "".equals(type)){
            return false;
        }
        String[] suffixWhiteList = typeWhiteList.split(",");
        //白名單匹配
        boolean anyMatch = Arrays.stream(suffixWhiteList).anyMatch(x -> x.equalsIgnoreCase(type));
        return anyMatch;
    }
}

 

發佈了27 篇原創文章 · 獲贊 32 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章