Java獲取文件的真實類型(通過文件魔數判斷文件類型)

背景

通常情況下,我們取文件的後綴名作爲文件的類型即可,但有時爲了防止用戶隨便修改後綴名,就需要獲取文件的真實類型。這時候可以通過文件的魔數來判別。魔數就是文件開頭的那幾個字節的數據。

代碼實現

工具類代碼
import java.util.HashMap;
import java.util.Map;

/**
 * @author lixk
 * @description 魔數工具類
 */
public class MagicNumberUtils {
    /**
     * 魔數到文件類型的映射集合
     */
    public static final Map<String, String> TYPES = new HashMap<>();

    static {
        // 圖片,此處只提取前六位作爲魔數
        TYPES.put("FFD8FF", "jpg");
        TYPES.put("89504E", "png");
        TYPES.put("474946", "gif");
        TYPES.put("524946", "webp");
    }

    /**
     * 根據文件的字節數據獲取文件類型
     *
     * @param data 文件字節數組數據
     * @return
     */
    public static String getFileType(byte[] data) {
        //提取前六位作爲魔數
        String magicNumberHex = getHex(data, 6);
        return TYPES.get(magicNumberHex);
    }

    /**
     * 獲取16進製表示的魔數
     *
     * @param data              字節數組形式的文件數據
     * @param magicNumberLength 魔數長度
     * @return
     */
    public static String getHex(byte[] data, int magicNumberLength) {
        //提取文件的魔數
        StringBuilder magicNumber = new StringBuilder();
        //一個字節對應魔數的兩位
        int magicNumberByteLength = magicNumberLength / 2;
        for (int i = 0; i < magicNumberByteLength; i++) {
            magicNumber.append(Integer.toHexString(data[i] >> 4 & 0xF));
            magicNumber.append(Integer.toHexString(data[i] & 0xF));
        }

        return magicNumber.toString().toUpperCase();
    }

}
單元測試類
import com.kalikali.userbiz.util.MagicNumberUtils;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * @author lixk
 * @description 文件魔數測試
 */
@SpringBootTest
public class MagicNumberUtilsTests {

    /**
     * 讀取文件字節數據
     *
     * @param filePath
     * @return
     * @throws IOException
     */
    public static byte[] getFileBytesData(String filePath) throws IOException {
        InputStream fs = new FileInputStream(filePath);
        byte[] b = new byte[fs.available()];
        fs.read(b);
        return b;
    }

    /**
     * 根據文件魔數獲取文件類型
     */
    @Test
    public void getFileType() throws Exception {
        System.out.println(MagicNumberUtils.getFileType(getFileBytesData("src/test/resources/images/1.jpg")));
        System.out.println(MagicNumberUtils.getFileType(getFileBytesData("src/test/resources/images/2.jpg")));
        System.out.println(MagicNumberUtils.getFileType(getFileBytesData("src/test/resources/images/1.png")));
        System.out.println(MagicNumberUtils.getFileType(getFileBytesData("src/test/resources/images/1.gif")));
        System.out.println(MagicNumberUtils.getFileType(getFileBytesData("src/test/resources/images/3.gif")));
        System.out.println(MagicNumberUtils.getFileType(getFileBytesData("src/test/resources/images/1.webp")));
    }
}

運行結果

在這裏插入圖片描述
如果需要判斷其他類型文件的真實類型,可以自行添加完善 魔數-類型 map.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章