java实现手机图片分类(2021.07.07)
背景:
我有整理手机照片的习惯,将手机照片和视频导入到电脑中时的样子是这样的:
杂乱无章,影响美感!
有不少照片是以时间戳的方式命名的,如:mmexport1537331635361.jpg尽管可以利用工具进行线上转化,然后再手动命名
这样虽然可以,但是效率虐低,还显得有点愚蠢,于是我想利用代码来进行自动分类,分类后的结果是这样的:
解决办法
-
将run.bat复制到要进行整理的文件夹下
-
双击
路径为jar包路径,run.bat 脚本如下:
java -jar D:\MyJava\2021.5_home\6.9-photoTimeGet\demo\target\demo.jar %~dp0
pause
上面的几个文件就自动被分配到了2个文件夹2018、2021中,文件夹就是他们名称中包含的时间
愉快的解决!
源码
import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.metadata.Metadata;
import org.apache.commons.imaging.ImageReadException;
import org.apache.commons.imaging.ImageWriteException;
import org.apache.commons.imaging.Imaging;
import org.apache.commons.imaging.common.ImageMetadata;
import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
import org.apache.commons.imaging.formats.jpeg.exif.ExifRewriter;
import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
import org.apache.commons.imaging.formats.tiff.constants.ExifTagConstants;
import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;
import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
public class M {
public static void main(String[] args){
demo(args[0]);
System.out.println("memeda... " + args[0]);
//demo("C:\\Users\\Administrator\\Desktop\\imgdemo\\2020.12-01\\D");
}
public static void demo(String dirName){
File file = new File(dirName);
String[] list = file.list();
for (String fileName : list) {
try {
//将形如以下三类的 直接进行分到月份文件中
//wx_20210601_050627、sc_20210703_153148、IMG_20210629_193059
if(fileName.startsWith("wx_20") || fileName.startsWith("sc_") || fileName.startsWith("IMG_")|| fileName.startsWith("VID_")){
situation3(dirName,fileName);
}else
//4.Screenshot_20210206_150129.jpg
if(fileName.startsWith("Sc")){
int start = 11;
situation14(start,dirName,fileName);
}
//2.mmexport1612178190861.jpg 2021-02-01 19:16:30
//3.wx_camera_1617879049583.jpg
else if(fileName.startsWith("mm") || fileName.startsWith("wx")){
//获取 年月
int start = fileName.startsWith("wx")?10:8;
situation23(start,dirName,fileName);
}
//1608219722461.mp4 1608219722461.jpeg
else if(fileName.length()==17 || fileName.length()==18){
//获取 年月
situation23(0,dirName,fileName);
}else {
System.out.println("未知类型图片 " + fileName);
continue;
}
}catch (Exception e){
System.out.println(fileName + "——————"+e);
}
}
}
private static void situation3(String dirName, String fileName) {
//wx_20210601_050627
//sc_20210703_153148
//IMG_20210629_193059
//获取 年月
String time = fileName.split("_")[1];
String year = time.substring(0,4);
String month = time.substring(4,6);
//创建文件夹
String newdirName = dirName+"\\"+year+"\\"+month;
File dirNew = new File(newdirName);
if(!dirNew.exists()){
dirNew.mkdirs();
}
String absPath = dirName+ "\\" + fileName;
move_file(absPath,newdirName,fileName,null);
}
//2.mmexport1612178190861.jpg 2021-02-01 19:16:30
//3.wx_camera_1617879049583.jpg
private static void situation23(int start,String dirName, String srcName) {
//获取 年月
long time2 = new Long(srcName.substring(start,start+13));
String timeStr = new SimpleDateFormat("yyyyMMdd_hhMMss").format(time2);
String year = timeStr.substring(0,4);
String month = timeStr.substring(4,6);
// 创建文件夹
String newdirName = dirName+"\\"+year+"\\"+month;
File dirNew = new File(newdirName);
if(!dirNew.exists()){
dirNew.mkdirs();
}
String newFileName = "wx_" + timeStr+srcName.substring(srcName.lastIndexOf("."));
String absoulteSrcPath = dirName +"\\" + srcName;
move_file(absoulteSrcPath,newdirName,srcName,newFileName);
}
//4.Screenshot_20210206_150129.jpg
private static void situation14(int start,String dirName,String fileName) {
// String timeStr = fileName.substring(11);
// 获取 年月
String year = fileName.substring(start,start+4);
String month = fileName.substring(start+4,start+6);
// 创建文件夹
File dirNew = new File(dirName+"/"+year+"/"+month);
if(!dirNew.exists()){
dirNew.mkdirs();
}
//Screenshot_20210614_104229_com.google.android.apps.maps
// 改为 sc_20210614_104229
//changePicTime(fileAbsPath,timeStr);
String[] s = fileName.split("_");
String newFileName = "sc_"+ s[1] + "_" + s[2]+".jpg";
String fileAbsPath = dirName + "/" + fileName;
move_file(fileAbsPath,dirNew.getAbsolutePath(),fileName,newFileName);
}
public static String move_file(String absoulteSrcPath, String absoulteDestDir,
String srcFileName,String newFileName){
//判断当前文件夹下是否有重名的文件
File file = new File(absoulteSrcPath);
newFileName = newFileName == null?file.getName():newFileName;
String[] list = new File(absoulteDestDir).list();
if(list!=null && list.length>0){
ArrayList<String> fileList = new ArrayList<>();
for (String s : list) {
fileList.add(s);
}
if(fileList.contains(newFileName)){
newFileName = createNewName(fileList,newFileName);
}
}
boolean b = file.renameTo(new File(absoulteDestDir,newFileName));
if(b){
System.out.println("成功----- "+srcFileName +" >> " + newFileName);
}else {
System.out.println("失败..... " +srcFileName);
}
return b?absoulteDestDir+"\\" + newFileName:null;
}
//生成不重名的文件名称
public static String createNewName(ArrayList<String> fileList, String s) {
String temp = s;
int count =1;
while (fileList.contains(temp)){
temp = s.split("\\.")[0]+"_"+count+"."+s.split("\\.")[1];
count++;
}
return temp;
}
}
打包
直接参考这个,有2点需要注意
- 路径直接选在src下就行
- main函数要选 src/main下的,不能选择test文件夹下的,不然报错。。
jar包百度云 提取码:6666
待优化,修改拍摄的时间
// "C:\\Users\\Administrator\\Desktop\\demo\\d.jpg"
// "1999:01:01 01:01:01"
// 将照片变为 20201006_120000.jpg 命名的照片,同时将照片的拍摄时间修改
public static void changePicTime(String fileAbsPath,String timeStr){
String newAbsPath = new File(fileAbsPath).getParent()+"\\"+timeStr.replace(" ","_").replace(":","")+".jpg";
//读文件
File file = new File(fileAbsPath);
boolean exists = file.exists();
try {
//获取ImageMetadata对象实例
ImageMetadata metadata = Imaging.getMetadata(file);
//强转为JpegImageMetadata
JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
if(jpegMetadata == null){
System.out.println(fileAbsPath + " 无法解析该照片...");
return;
}
//获取TiffImageMetadata
TiffImageMetadata exif = jpegMetadata.getExif();
//转换为Tiff的流
TiffOutputSet out = exif.getOutputSet();
//获取TiffOutputDirectory
TiffOutputDirectory exifDirectory = out
.getOrCreateExifDirectory();
//移除拍摄时间
exifDirectory.removeField(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL);
exifDirectory.removeField(ExifTagConstants.EXIF_TAG_DATE_TIME_DIGITIZED);
//初始化当前时间
//String date = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss").format(new Date());
//添加拍摄时间,格式为yyyy:MM:dd HH:mm:ss
exifDirectory.add(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL, timeStr);
exifDirectory.add(ExifTagConstants.EXIF_TAG_DATE_TIME_DIGITIZED,timeStr);
//新建输出流保存文件
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newAbsPath));
//写图片
new ExifRewriter().updateExifMetadataLossless(file, bos, out);
} catch (ImageReadException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ImageWriteException e) {
e.printStackTrace();
}finally {
file.delete();
}
}