目录

前言

一、如何获取真实文件格式?

二、发开步骤

1. 定义枚举类,建立常见的文件类型与文件头魔数对应关系

2.新建GetFileTypeUtil工具类,获取文件格式

3.使用方法

总结


前言

今天在做文件上传下载的功能,前端需要我把文件转成base64编码给她。但是发现Java base64转码会缺失data数据,这样也就无法识别该文件是什么类型的,于是想写个工具类获取文件类型,追加上去。开始是想根据文件后缀名判断的,但这样要是故意修改文件后缀就无法准确判断了。在咨询一番度娘后,决定采用读取文件的十六进制文件头来判断文件的真正类型。


提示:以下是本篇文章正文内容,下面内容仅供个人学习记录,欢迎评论交流学习

一、如何获取真实文件格式?

当把文件的二进制数据转换成十六进制时,同类型文件的文件头数据是相同的,即使改变了其后缀,这个数据也不会改变。文件头是位于文件开头的一段承担一定任务的数据,一般在开头部分。头文件作为一种包含功能函数、数据接口声明的载体文件,用于保存程序声明(declaration),而定义文件用于保存程序的实现(implementation)。一般文件头开始几节数据是固定的,被称为魔数,作为区分文件类型的硬添加进去的数据。(例如PNG格式的十六进制文件头数据就是以"89504E47"开头的,就可以判定该文件是PNG格式)为了解决在用户上传文件的时候在服务器端判断文件类型的问题,故用获取文件头的方式,直接读取文件的前几个字节,来判断文件的真实类型。

二、发开步骤

1. 定义枚举类,建立常见的文件类型与文件头魔数对应关系

代码如下(示例):

package com.ruoyi.vip.fileLearn;public enum FileType {/*** JEPG.*/JPEG("FFD8FF"),/*** PNG.*/PNG("89504E47"),/*** GIF.*/GIF("47494638"),/*** TIFF.*/TIFF("49492A00"),TXT("6C657420"),/*** 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).*/PST("2142444E"),/*** MS Word/Excel.*/XLS_DOC("D0CF11E0"),/*** MS Access.*/MDB("5374616E64617264204A"),/*** WordPerfect.*/WPD("FF575043"),/*** Postscript.*/EPS("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).*/MPG("000001BA"),/*** Quicktime.*/MOV("6D6F6F76"),/*** Windows Media.*/ASF("3026B2758E66CF11"),GZ("1F8B08"),/*** MIDI.*/MID("4D546864");private String value = "";/*** Constructor.* @param value*/private FileType(String value) {this.value = value;}public String getValue() {return value;}public void setValue(String value) {this.value = value;}
}

2.新建GetFileTypeUtil工具类,获取文件格式

代码如下(示例):

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;/*** @description 判断文件类型工具类* @author 13192*/
public class GetFileTypeUtil {/*** @description 第一步:获取文件输入流* @param filePath* @throws IOException*/private static String getFileContent(String filePath) throws IOException {byte[] b = new byte[20];InputStream inputStream = null;try {inputStream = new FileInputStream(filePath);/*** int read() 从此输入流中读取一个数据字节。int read(byte[] b) 从此输入流中将最多 b.length* 个字节的数据读入一个 byte 数组中。 int read(byte[] b, int off, int len)*从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。* 之所以从输入流中读取20个字节数据,是因为不同格式的文件头魔数长度是不一样的,比如 EML("44656C69766572792D646174653A")和GIF("47494638")* 为了提高识别精度所以获取的字节数相应地长一点*/inputStream.read(b, 0, 20);} catch (IOException e) {e.printStackTrace();throw e;} finally {if (inputStream != null) {try {inputStream.close();} catch (IOException e) {e.printStackTrace();throw e;}}}return bytesToHexString(b);}/*** @description 第二步:将文件头转换成16进制字符串* @param* @return 16进制字符串*/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);}System.out.println("文件类型16进制字符串是"+stringBuilder.toString());return stringBuilder.toString();}/*** @description 第三步:根据十六进制字符串判断文件类型格式* @param filePath 文件路径* @return 文件类型*/public static FileType getType(String filePath) throws IOException {String fileHead = getFileContent(filePath);if (fileHead == null || fileHead.length() == 0) {return null;}fileHead = fileHead.toUpperCase();FileType[] fileTypes = FileType.values();for (FileType type : fileTypes) {
//            startsWith() 方法用于检测字符串是否以指定的前缀开始if (fileHead.startsWith(type.getValue())) {return type;}}return null;}
}

3.使用方法

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;/*** @author : MasterWei* @date : 2020-12-10 21:53* @description :* @params :* @return :**/
public class test {public static void main(String[] args) throws Exception {//故意把png文件的后缀改成txt,看是否能获取到真实文件格式final String filePath = getFileType("C:\\Users\\13192\\Pictures\\123.png.txt");String name=GetFileTypeUtil.getType(filePath).name();System.out.println("文件格式是"+name);}


总结

本文简单示例了Java如何获取真实文件格式的小demo,其中FileType枚举类可以在实际应用中添加更多对应的魔数,以增强识别读。

Java 获取文件的真实类型,修改后缀名也能识别出来相关推荐

  1. 图片可隐藏zip和mp3文件,只需修改后缀名,这个GitHub项目火了

    晓查 发自 凹非寺  量子位 报道 | 公众号 QbitAI 明明下载的是一张图片,只需修改后缀名,图片就变成了一首歌,一串Python代码. 国外黑客David Buchanan利用Twitter的 ...

  2. Qt 中获取文件路径和文件名、后缀名(连续多个后缀名)

    QString fileName, filePath,fileSuffix;     QString fullPath = QFileDialog::getOpenFileName(this,.... ...

  3. Java获取文件类型的5种方法

    前言 工作中经常会用到,判断一个文件的文件类型,这里总结一把,一般判断文件类型的原理有2种方式: 根据文件扩展名判断 优点:速度快,代码简单 缺点:无法判断出真实的文件类型,例如一些伪造的文件或者没有 ...

  4. java获取文件编码

    目录 1. 概述 2. 编码基本知识 2.1. iso8859-1 2.2. GB2312/GBK 2.3. unicode 2.4. UTF 3.JAVA中移位运算>> , <&l ...

  5. java获取文件列表,[javaSE] java获取文件列表

    递归测试 import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.Lis ...

  6. 如何获取服务器上文件的hashcode,java获取文件hashcode

    java获取文件hashcode [2021-02-05 18:36:57]  简介: php去除nbsp的方法:首先创建一个PHP代码示例文件:然后通过"preg_replace(&quo ...

  7. java 获取文件扩展名_如何在Java中获取文件扩展名

    java 获取文件扩展名 Sometimes while working with files, we need to process them differently based on their ...

  8. Java实现文件拷贝,以及修改文件扩展名

    Java实现文件拷贝,以及修改文件扩展名 方法一:单纯实现文件拷贝 public File createNewFile(String path, String realPath, String new ...

  9. Android 打开文件管理器 获取文件的真实路径

    1. onCreate 部分 public class MainActivity extends AppCompatActivity { Button btn; @Override protected ...

  10. Linux怎么查找指定后缀名文件以及批量修改后缀名

    今天做了一道Linux的题目,题目如下: 其中查找并不难实现,使用find语句:find /var/log -name "*.log" 就可以实现,shell脚本如下: #!/bi ...

最新文章

  1. 为什么那么多程序员不敢学Python?
  2. php5.5 mysql网站空间_PHP环境配置IIS5.0+PHP5.23+MYSQL5+phpMyAdmin
  3. ##连接符和#符的使用
  4. python中and和or的惰性求值特点_python中的惰性求值
  5. android学习之路1:前车之鉴之开发环境搭建
  6. android 广播观察者,作业三——观察者模式在Android广播机制上的应用
  7. 运行Android Studio自带模拟器报:Guest isn't online after 7 second...
  8. 在线网络投票/打分活动实施步骤及疑难问题汇编
  9. 几个实用又好看的纯css 按钮样式
  10. 菲利普·安德森:凝聚态物理的艺术家
  11. 显示器分辨率、显示器大小和视频分辨率的关系
  12. PDF转word的两种办法
  13. 推荐一个简单好用的HTML编辑器
  14. RTX3070深度学习环境配置
  15. [leetcode]剑指offer(C++版题解)
  16. rootfs bootfs bootloader
  17. 如果你喜欢平板又是QWERTY键盘控 联想推“握柄键盘”满足你
  18. 头像上传(限制大小,格式,尺寸)
  19. Docker出现exited(127)的解决方法
  20. Xilinx Ultrascale 多通道高速TDC

热门文章

  1. 吐槽一下程序员职场那些令人迷惑的行为
  2. 杂牌平板mt6797_联发科MT6797炸现跑分库 强得令人毛骨悚然
  3. 谷歌智能眼镜再掀数码浪潮
  4. 能不能算是PLSQL Developer的锅?
  5. KMP 深入理解next数组
  6. 天津滨海农商银行数据脱敏建设实践
  7. 《经济学的思维方式》内容
  8. 直播系统开发:宋祖儿直播自曝“抠脚妹”
  9. 电容式计算机键盘的按键下,计算机键盘开关
  10. jsp中打开新的html网页,jsp中用window.open()打开新页面的相关设置