Java 提取照片的EXIF信息批量重命名
作者:攻城狮·正 发布时间:2023-10-05 14:11:28
标签:Java,EXIF,重命名
手机或照机拍摄的照片名称通常是”IMG_001.JPG”这种格式,这种文件名称是无意义的。使用照片拍摄时间命名可以让我们在多年以后查找照片时根据文件名就能快速筛选出某一时间段的照片。
原始照片或视频是带有EXIF信息的。这些信息是设备在拍摄时生成,记录了照片的拍摄时间,设备信息,拍摄GPS位置等信息,在文件属性中可以查看到:
图片APP和网盘软件中图片时间线也是提取EXIF信息生成的。如果对照片进行处理,如美化操作,另存为时可能会丢失EXIF信息,或者EXIF信息被改写,会导致识别信息不准。
我以前备份的照片,大多是原始文件名,现在我想根据拍摄日期批量重命名。
找了一圈,发现老牌看图软件ADSee带有这个功能:
但是存在几个问题:
不能排除已丢失EXIF的文件,这类的文件无法重命名
官方ADSee免费版下载安装后,要注册账号才能使用
于是动动手,用JAVA代码实现这个小功能。
提取EXIF信息使用的是开源项目 metadata extractor ,它支持市面上常见的媒体文件格式和设备:
metadata extractor 官网:https://drewnoakes.com/code/exif/
引入依赖:
<dependency>
<groupId>com.drewnoakes</groupId>
<artifactId>metadata-extractor</artifactId>
<version>2.15.0</version>
</dependency>
官方读取示例代码:
Metadata metadata = ImageMetadataReader.readMetadata(file);
for (Directory directory : metadata.getDirectories()) {
for (Tag tag : directory.getTags()) {
System.out.format("[%s] - %s = %s \n",
directory.getName(), tag.getTagName(), tag.getDescription());
}
if (directory.hasErrors()) {
for (String error : directory.getErrors()) {
System.err.format("ERROR: %s", error);
}
}
}
以下是我使用示例代码读取一张图片输出的部分结果:
其中 Date/Time Original 就是我要取的摄像日期。
代码如下:
/**
* 如果是目录则递归查找
* @param file 文件或目录
*/
public static void recursion(File file) {
if (file.isDirectory()) {
// 目录
File[] fileList = file.listFiles();
for (File f : fileList) {
recursion(f);
}
} else {
// 文件
if (file.isFile()) {
// 格式:2019:06:27 11:23:55 或 2019:07:13 19:07:42下午
String originDateTime = getOriginDateTime(file);
if (null != originDateTime) {
int lastDoc = file.getPath().lastIndexOf(".");
String suffix = file.getPath().substring(lastDoc);
String fileName = originDateTime.replace("下午", "").replaceAll(":", "-") + suffix;
File newFile = new File(file.getParentFile(), fileName);
if (newFile.exists()) {
System.out.format("文件【%s】已存在 \n", newFile.getPath());
} else {
System.out.format("重命名【%s】 -> 【%s】 \n", file.getPath(), newFile.getPath());
file.renameTo(newFile);
}
} else {
System.out.format("文件【%s】中未找到 Origin DateTime 信息 \n", file.getPath());
}
}
}
}
/**
* 提取拍摄日期
* @param file
* @return
*/
public static String getOriginDateTime(File file) {
String originDateTime = null;
try {
Metadata metadata = ImageMetadataReader.readMetadata(file);
for (Directory directory : metadata.getDirectories()) {
for (Tag tag : directory.getTags()) {
if ("Date/Time Original".equals(tag.getTagName())) {
// System.out.format("[%s] - %s = %s \n",
// directory.getName(), tag.getTagName(), tag.getDescription());
originDateTime = tag.getDescription();
}
}
if (directory.hasErrors()) {
for (String error : directory.getErrors()) {
System.err.format("ERROR: %s %s \n", error, file.getPath());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return originDateTime;
}
Main方法测试:
public static void main(String[] args) throws ImageProcessingException, IOException {
recursion(new File("图片目录"));
}
执行结果:
可以根据自己需求重写重命名方法。比如在拍摄日期相同时加上一个自增数。
来源:https://engr-z.com/393.html


猜你喜欢
- SpringBoot的主要目的是简化配置文件,通过少量配置即可运行Java程序,其强大的自动配置功能帮助开发者轻松实现配置装配,通过引入Sp
- 起因曾经用过西门子出的 * , 好处是直接有SDK开发包, 不会硬件开发也能直接使用缺点也是明显的, 就是只支持Windows系统, 另外就
- 先随便创建一个存储过程DELIMITER $$CREATE PROCEDUREgetUserNameById (IN i_id BIGINT
- 背景公司的开发框架集成了附件本地存储,阿里云,华为云等,现项目有要求附件存储与应用部署环境不能是同一台服务器,也不能使用云存储,经过技术选型
- WPF在样式定义和UI动画上面相对于以前的技术有了不少的提升,下面给出WPF技术实现钟表的效果:1、Visual Studio新建一个WPF
- 过滤器是Servlet的规范,是基于函数回调的,需要实现javax.servlet.Filter接口,依赖于Tomcat等容器,一般用于过滤
- 题目给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。示例 1:输入: 123输出: 321 示例
- 目前在做项目中有处理图片的部分,参考了一下网上案例,自己写了一个获取内容中的图片地址的方法。 一般来说一个 HTML 文档有很多标
- Interfaces 接口在软件工程中,由一份“契约”规定来自不同的开发小组的软件之间如何相互作用是非常常见的。每个小组都可以在不知道别的组
- 最近要做一个网站,要求实现验证码程序,经过不断调试,终于成功实现功能。一、验证码生成类生成验证码的话需要用到java的Graphics类库,
- 本文实例讲述了C#自定义缓存封装类。分享给大家供大家参考。具体如下:这个自定义的C#类封装了部分常用的缓存操作,包括写入缓存,读取缓存,设置
- Jenkins是一个开源软件项目,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能Jenkins是基于Java开发的一种持续集成工具
- Spring-Data-Redis项目(简称SDR)对Redis的Key-Value数据存储操作提供了更高层次的抽象,类似于Spring F
- 官方的C/C++插件是支持使用.clang-format配置文件进行自定义风格代码格式化的,无需另外安装clang-format插件。但是使
- xxx cannot be resolved to a type引言 eclipse新导入的项目经常可以
- 提几个问题,从问题中去了解去学习:他们之间有啥区别?如果我使用notify(),将通知哪个线程?我怎么知道有多少线程在等待,所以我可以使用n
- AOP我想大家都很清楚,有时候我们需要处理一些请求日志,或者对某些方法进行一些监控,如果出现例外情况应该进行怎么样的处理,现在,我们从spr
- FrameLayout 在这个布局中,所有的子元素都不能被指定放置的位置,他们统统防御这块区域的左上角, 并且后面的子元素直接覆盖在前面的子
- 在spring Boot中,有些代码是WEB功能,例如API等,但是有些逻辑是非WEB,启动时就要调用并持续运行的,该如何加载自己的非WEB
- 本文实例讲述了基于.net实现裁剪网站上传图片的方法。由于客户端Javascript不能操作文件,所以只能先上传图片再在服务器端剪切。1、上