package com.kwan.springbootkwan.utils; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.StopWatch; import com.alibaba.fastjson2.JSON; import com.google.common.base.Charsets; import com.google.common.io.Files; import lombok.extern.slf4j.Slf4j; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.stream.Collectors; /** * 删除博客中不存在的照片 * * @author : qinyingjie * @version : 2.2.0 * @date : 2023/2/8 10:45 */ @Slf4j public class FileContainsUtil { /** * 默认图片不存在 */ private static ThreadLocal IS_EXIST = ThreadLocal.withInitial(() -> false); /** * 图片路径 */ private static final String PIC_PATH = "/Users/qinyingjie/Documents/idea-workspace/blogimg/"; /** * 博客路径1 */ private static final String BLOG_FOLDER1 = "/Users/qinyingjie/Documents/vscode-workspace/blog/"; /** * 博客路径2 */ private static final String BLOG_FOLDER2 = "/Users/qinyingjie/Documents/idea-workspace/study/blog/"; /** * 博客路径3 */ private static final String BLOG_FOLDER3 = "/Users/qinyingjie/Documents/idea-workspace/study/belle_blog/"; /** * 图片白名单 */ private static final List PIC_PATH_WHITELISTS = Arrays.asList( "http://qinyingjie.top/blogImg/image-20230324112725149.png" , "http://qinyingjie.top/blogImg/logo.png" , "http://qinyingjie.top/blogImg/image-20230601124308164.png" , "http://qinyingjie.top/blogImg/image-20230822102858692.png" ); public static void main(String[] args) throws Exception { StopWatch stopWatch = new StopWatch(); currentTime("开始时间"); stopWatch.start("删除未用到的图片"); //不存在的图片集合 final List isNotExist = new ArrayList<>(); //获取所有图片名称 final List picNames = getPicName(PIC_PATH); final int size = picNames.size(); log.info("图片总数为{}", size); List> groupedPicNames = dataGroup(picNames); moreThread(groupedPicNames, isNotExist); log.info("不存在图片总数为{}", isNotExist.size()); stopWatch.stop(); //毫秒输出 log.info("耗时统计信息:{}", JSON.toJSONString(stopWatch.getTaskInfo())); log.info("耗时秒数:{}", JSON.toJSONString(stopWatch.getTotalTimeSeconds())); log.info("耗时分钟数:{}", JSON.toJSONString(stopWatch.getTotalTimeSeconds() / 60)); currentTime("结束时间"); } /** * 多线程处理图片任务 * * @param groupedPicNames * @param isNotExist */ private static void moreThread(List> groupedPicNames, List isNotExist) { // 创建并启动4个线程来处理每个组的任务 List threads = new ArrayList<>(); for (int i = 0; i < 6; i++) { final List group = groupedPicNames.get(i); Thread thread = new Thread(() -> { // 在这里执行处理图片组的任务 if (CollectionUtil.isNotEmpty(group)) { for (String picName : group) { // 处理图片文件 picName //是白名单里面的图片,直接忽略 for (String picPathWhitelist : PIC_PATH_WHITELISTS) { if (picPathWhitelist.contains(picName)) { continue; } } //默认不存在 IS_EXIST.set(false); //包含某个字符串 try { traverseFolder(BLOG_FOLDER1, picName); traverseFolder(BLOG_FOLDER2, picName); traverseFolder(BLOG_FOLDER3, picName); } catch (Exception e) { e.printStackTrace(); } //文件不存在 if (!IS_EXIST.get()) { isNotExist.add(picName); deletePic(PIC_PATH + picName); } } } }); thread.start(); threads.add(thread); } // 等待所有线程完成 for (Thread thread : threads) { try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } } /** * 数据分组 * 经过测试6组和8组的时间基本一致,线程数并不是越大越好 * * @param picNames * @return */ private static List> dataGroup(List picNames) { int groupSize = picNames.size() / 6; // 计算每组的大小 List> groupedPicNames = picNames.stream() .collect(Collectors.groupingBy(e -> picNames.indexOf(e) / groupSize)) .values() .stream() .collect(Collectors.toList()); return groupedPicNames; } /** * 获取文件 * * @param path * @param word * @throws IOException */ public static void traverseFolder(String path, String word) throws Exception { File file = new File(path); if (file.exists()) { //获取文件夹下的文件 File[] files = file.listFiles(); if (null != files && files.length != 0) { for (File file2 : files) { //是否是文件夹 if (file2.isDirectory()) { traverseFolder(file2.getAbsolutePath(), word); } else { //包含md结尾的文件 if (file2.getAbsolutePath().contains(".md")) { getParams(file2.getAbsolutePath(), word); } } } } } } /** * 判断文件是否存在 * * @param classPath * @param word * @throws IOException */ public static void getParams(String classPath, String word) throws IOException { File file = new File(classPath); //每行作为一个字符串,存为列表元素 List strings = Files.readLines(file, Charsets.UTF_8); for (String string : strings) { //判断是否包含方法名称,即指定字符串 if (string.contains(word)) { //文件存在 IS_EXIST.set(true); } } } /** * 获取图片名称 * * @param path * @return */ public static List getPicName(String path) { List picNames = new ArrayList<>(); File file = new File(path); if (file.exists()) { //获取文件夹下的文件 File[] files = file.listFiles(); if (null != files && files.length != 0) { for (File file2 : files) { //是否是文件夹 if (!file2.isDirectory()) { //包含md结尾的文件 final String name = file2.getName(); picNames.add(name); } } } } return picNames; } /** * 删除文件 * * @param picPath */ public static void deletePic(String picPath) { File file = new File(picPath); try { file.delete(); System.out.printf("删除文件成功:%s%n", picPath); } catch (Exception e) { System.err.printf("无法删除的路径 %s%n%s", picPath, e); } } /** * 打印当前时间 * * @param str */ public static void currentTime(String str) { // 获取当前时间 Date currentTime = new Date(); // 创建一个格式化器以将时间转换为所需的格式 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 使用格式化器将时间转换为字符串并打印 String formattedTime = dateFormat.format(currentTime); System.out.println(str + ":" + formattedTime); } }