• Java依据文件头获取文件类型


    简介

    文件头是位于文件开头的一段承担一定任务的数据,一般都在开头的部分。头文件作为一种包含功能函数、数据接口声明的载体文件,用于保存程序的声明(declaration),而定义文件用于保存程序的实现 (implementation)。

    为了解决在用户上传文件的时候在服务器端判断文件类型的问题,故用获取文件头的方式,直接读取文件的前几个字节,来判断上传文件是否符合格式。

    问题

    现有一文件,其扩展名未知或标记错误。假设它是一个正常的、非空的文件,且将扩展名更正后可以正常使用,那么,如何判断它是哪种类型的文件?

    在后缀未知,或者后缀被修改的文件,依然通过文件头来判断该文件究竟是什么文件类型。我们可以使用一个文本编辑工具如 UltraEditUniversalViewer 打开文件(16进制模式下),然后看文件头是什么字符,以下是常见文件类型的文件头字符(16进制),希望对你有帮助:

    文件 文件头
    JPEG (jpg) FFD8FF
    PNG (png) 89504E47
    GIF (gif) 47494638
    TIFF (tif) 49492A00
    Windows Bitmap (bmp) 424D
    CAD (dwg) 41433130
    Adobe Photoshop (psd) 38425053
    Rich Text Format (rtf) 7B5C727466
    XML (xml) 3C3F786D6C
    HTML (html) 68746D6C3E
    Email [thorough only] (eml) 44656C69766572792D646174653A
    Outlook Express (dbx) CFAD12FEC5FD746F
    Outlook (pst) 2142444E
    MS Word/Excel (xls.or.doc) D0CF11E0
    MS Access (mdb) 5374616E64617264204A
    WordPerfect (wpd) FF575043
    Postscript (eps.or.ps) 252150532D41646F6265
    Adobe Acrobat (pdf) 255044462D312E
    Quicken (qdf) AC9EBD8F
    Windows Password (pwl) E3828596
    ZIP Archive (zip) 504B0304
    RAR Archive (rar) 52617221
    Wave (wav) 57415645
    AVI (avi) 41564920
    Real Audio (ram) 2E7261FD
    Real Media (rm) 2E524D46
    MPEG (mpg) 000001BA
    MPEG (mpg) 000001B3
    Quicktime (mov) 6D6F6F76
    Windows Media (asf) 3026B2758E66CF11
    MIDI (mid) 4D546864

    源码

    package com.blog.www.util;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 文件类型
     * <br/>
     *
     * @author :leigq
     * @date :2019/7/30 10:07
     */
    public class FileTypes {
    
    	private static final Map<FileTypeName, String> FILE_TYPE_MAP = new HashMap<>();
    
    	static {
    		// 初始化文件类型信息
    		initAllFileType();
    	}
    
    	private FileTypes() {
    	}
    
    	/**
    	 * 文件类型名称枚举
    	 * <br/>
    	 *
    	 * @author :leigq
    	 * @date :2019/7/30 10:20
    	 */
    	public enum FileTypeName {
    
    		JPG("jpg"),
    
    		PNG("png"),
    
    		GIF("gif"),
    
    		// ....根据自己需要添加更多
    		;
    
    		private String fileTypeName;
    
    		FileTypeName(String fileTypeName) {
    			this.fileTypeName = fileTypeName;
    		}
    
    		@Override
    		public String toString() {
    			return fileTypeName;
    		}
    	}
    
    	/**
    	 * 验证文件类型
    	 * <br/>
    	 * create by: leigq
    	 * <br/>
    	 * create time: 2019/7/30 10:25
    	 *
    	 * @param fileTypeName 文件类型名称枚举
    	 * @param file         文件
    	 * @return if 文件类型 = 文件类型名称枚举 return true , else return false
    	 */
    	public static Boolean checkType(FileTypeName fileTypeName, File file) {
    		try {
    			FileInputStream fileInputStream = new FileInputStream(file);
    			byte[] b = new byte[10];
    			// 读取文件前10个字节
    			int read = fileInputStream.read(b, 0, b.length);
    			if (read != -1) {
    				// 将字节转换为16进制字符串
    				String fileCode = bytesToHexString(b).toUpperCase();
    				// 获取对应文件类型的文件头
    				String fileTypeHead = FILE_TYPE_MAP.get(fileTypeName);
    				return fileCode.startsWith(fileTypeHead) || fileTypeHead.startsWith(fileCode);
    			}
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		return false;
    	}
    
    
    	/**
    	 * 获取文件类型
    	 *
    	 * @param file 文件
    	 * @return 文件类型,if 获取不到类型 return "-1"
    	 */
    	public static String getType(File file) {
    		try {
    			FileInputStream is = new FileInputStream(file);
    			byte[] b = new byte[10];
    			int read = is.read(b, 0, b.length);
    			if (read != -1) {
    				String fileCode = bytesToHexString(b).toUpperCase();
    				for (Map.Entry<FileTypeName, String> next : FILE_TYPE_MAP.entrySet()) {
    					String fileTypeHead = next.getValue();
    					if (fileTypeHead.startsWith(fileCode) || fileCode.startsWith(fileTypeHead)) {
    						return next.getKey().toString();
    					}
    				}
    			}
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		return "-1";
    	}
    
    	/**
    	 * 初始化常见文件头信息
    	 * <br/>
    	 * create by: leigq
    	 * <br/>
    	 * create time: 2019/7/30 10:19
    	 */
    	private static void initAllFileType() {
    		// JPEG (jpg)
    		FILE_TYPE_MAP.put(FileTypeName.JPG, "FFD8FF");
    
    		// PNG (png)
    		FILE_TYPE_MAP.put(FileTypeName.PNG, "89504E47");
    
    		// GIF (gif)
    		FILE_TYPE_MAP.put(FileTypeName.GIF, "47494638");
    
    		// ....根据自己需要添加更多, 文件头编码请用大写
    	}
    
    	/**
    	 * 将字节数组转换成16进制字符串
    	 *
    	 * @param bytes 待转换字节数组
    	 */
    	private static String bytesToHexString(byte[] bytes) {
    		StringBuilder stringBuilder = new StringBuilder();
    		for (byte b : bytes) {
    			int v = b & 0xFF;
    			String hv = Integer.toHexString(v);
    			if (hv.length() < 2) {
    				stringBuilder.append(0);
    			}
    			stringBuilder.append(hv);
    		}
    		return stringBuilder.toString();
    	}
    
    }
    

    测试

    /**
     * 测试
     * <br/>
     * create by: leigq
     * <br/>
     * create time: 2019/7/30 11:32
     */
    public static void main(String[] args) {
        // 验证 PNG
        File pngImg = new File("C:\file_type\png_test.png");
        System.out.println(checkType(FileTypeName.PNG, pngImg));
        System.out.println(getType(pngImg));
    
        System.out.println("------------------");
    
        // 验证 JPG
        File jpgImg = new File("C:\file_type\jpg_test.jpg");
        System.out.println(checkType(FileTypeName.JPG, jpgImg));
        System.out.println(getType(jpgImg));
    
        System.out.println("------------------");
    
        // 验证 GIF
        File gifImg = new File("C:\file_type\gif_test.gif");
        System.out.println(checkType(FileTypeName.GIF, gifImg));
        System.out.println(getType(gifImg));
    
        System.out.println("------------------");
    
        // 验证 未知类型文件
        File unknown = new File("C:\file_type\123.md");
        System.out.println(checkType(FileTypeName.GIF, unknown));
        System.out.println(getType(unknown));
    }
    

    在这里插入图片描述

    参考


    作者:不敲代码的攻城狮
    出处:https://www.cnblogs.com/leigq/
    任何傻瓜都能写出计算机可以理解的代码。好的程序员能写出人能读懂的代码。

     
  • 相关阅读:
    CPDA之时间序列
    CSS clear
    27 款经典的CSS 框架
    IT人必读:请不要做浮躁的IT人
    23个Javascript弹出窗口特效
    三种东西永远不要放到数据库里
    jquery 插件 thickbox窗口 第一个控件获得焦点(解决第二次弹出窗口,文本不能输入数据)
    enum总结
    vs版本的选择
    iPhone iPad 各种控件默认高度
  • 原文地址:https://www.cnblogs.com/leigq/p/13406540.html
Copyright © 2020-2023  润新知