使用tinypng和多线程压缩文件目录中的jpg和png图片

遍历一个目录中的jpg和png图片,压缩其中x文件夹中的x.jpg,x.png图片(x不是具体文件名称)

例子

 

工具类

public class ComPressUtils {

    private final static Logger log = LoggerFactory
            .getLogger(ComPressUtils.class);

    // 配置文件路径(存储被压缩图片的信息,键值对保存,键:图片路径,值:压缩后图片MD5加密)
    public static final String FILE_NAME = "keyvalue.properties";// 要创建的文件名
    public static final String FILE_PATH = "C:/Users/admin/Desktop/pic/";// 文件指定存放的路径

    // 搜索压缩图片的目录
    private static final String IMGPATH = "C:/Users/admin/Desktop/pic";

    private static ExecutorService ALL_TASKES = null;// 队列的最大任务数
    // 当前任务各个图片压缩情况
    private static final List<Future<String>> RESULT_LIST = new ArrayList<Future<String>>();

    public static void main(String[] args) throws IOException {

        // 加载配置文件信息,获取已被压缩的图片
        Map<String, Object> compressImgMap = initConfigFile();

        // 搜索压缩的图片
        List<String> result = new ArrayList<>();// 存储要压缩的图片路径
        log.info("准备搜索目标文件");
        File file = new File(IMGPATH);
        getNeedCompressImg(file, result);
        log.info("搜索目标文件结束");
        for (String s : result) {
            log.info("搜索结果" + s);
        }

        // 压缩搜索到的图片替换旧图片
        log.info("准备压缩目标图片");
        ALL_TASKES = Executors.newFixedThreadPool(3);
        for (String s : result) {
            Callable<String> oneCallable = new CompressImgTask(s,
                    compressImgMap);
            Future<String> oneTask = ALL_TASKES.submit(oneCallable);

            RESULT_LIST.add(oneTask);
        }
        for (Future<String> f : RESULT_LIST) {
            try {
                log.info(f.get());
            } catch (Exception e) {
                log.error("压缩异常", e);
            }
        }

    }

    /**
     * 搜索需要压缩的图片
     * 
     * @param imgPath
     */
    private static void getNeedCompressImg(File file, List<String> result) {

        // 获取指定目录下当前所有文件夹或者文件对象
        File[] files = file.listFiles();
        for (int i = 0; i < files.length; i++) {
            if (files[i].isDirectory()) {// 文件夹,进一步遍历文件夹内容
                getNeedCompressImg(files[i], result);
            } else {
                // 文件夹名
                String fileName = file.getName();
                // 文件夹里文件
                String childrenFileName = files[i].getName();// 文件全名(包含扩展名)
                String name = childrenFileName.substring(0,
                        childrenFileName.lastIndexOf("."));// 文件名(不包含扩展名)
                String fileTyle = childrenFileName.substring(
                        childrenFileName.lastIndexOf(".") + 1,
                        childrenFileName.length());// 文件的扩展名

                if (null != fileName && null != name) {
                    if (fileName.equals(name)) {
                        if ("jpg".equals(fileTyle) || "png".equals(fileTyle)) {
                            result.add(files[i].getAbsolutePath());
                        }
                    }
                }
            }
        }

    }

    /**
     * 加载配置文件信息
     * 
     * @param configFilePath
     */
    private static Map<String, Object> initConfigFile() {

        Map<String, Object> result = new HashMap<>();// 图片路径:图片MD5加密
        String configFilePath = FILE_PATH + FILE_NAME;

        File folder = new File(FILE_PATH);
        // 文件夹路径不存在
        if (!folder.exists() && !folder.isDirectory()) {
            log.info("文件夹路径不存在,创建路径:" + FILE_PATH);
            folder.mkdirs();
            log.info("文件夹创建成功");
        } else {
            log.info("文件夹路径存在:" + FILE_PATH);
        }

        // 判断配置文件是否存在
        File file = new File(configFilePath);
        if (file.exists()) {
            log.info("配置文件存在,开始加载配置文件");
            Properties prop = new Properties();
            try {
                InputStream in = new BufferedInputStream(
                        new FileInputStream(configFilePath));// 读取配置文件
                prop.load(in); /// 加载配置文件
                Iterator<String> it = prop.stringPropertyNames().iterator();
                while (it.hasNext()) {
                    String key = it.next();
                    result.put(key, prop.getProperty(key));
                }
                in.close();
                log.info("加载配置文件成功");
            } catch (FileNotFoundException e) {
                log.info("读取配置文件失败!");
                e.printStackTrace();
            } catch (IOException e) {
                log.info("加载配置文件失败!");
                e.printStackTrace();
            }
        } else {
            log.info("配置文件不存在,正在创建配置文件!");
            try {
                file.createNewFile();
                log.info("配置文件创建成功!");
            } catch (IOException e) {
                log.info("配置文件创建失败!");
                e.printStackTrace();
            }
        }

        return result;
    }

}

 

public class CompressImgTask implements Callable<String> {

    private final static Logger log = LoggerFactory
            .getLogger(CompressImgTask.class);

    // 配置文件路径(存储被压缩图片的信息,键值对保存,键:图片路径,值:压缩后图片MD5加密)
    public static final String FILE_NAME = "keyvalue.properties";// 要创建的文件名
    public static final String FILE_PATH = "C:/Users/admin/Desktop/pic/";// 文件指定存放的路径

    private String s;
    private Map<String, Object> compressImgMap;

    public CompressImgTask(String s, Map<String, Object> compressImgMap) {
        super();
        this.s = s;
        this.compressImgMap = compressImgMap;
    }

    @SuppressWarnings("resource")
    @Override
    public String call() throws Exception {
        Properties prop = new Properties();

        Tinify.setKey(你的timypng码,去官网注册);

        Source source;
        File imgFile;
        String byteStr;
        FileOutputStream oFile = new FileOutputStream(FILE_PATH + FILE_NAME,
                true);// true表示追加打开
        byte[] byteArray;
        try {
            log.info("开始压缩目标图片:" + s);
            // 获取旧图片的绝对路径和名称
            imgFile = new File(s);
            String path = imgFile.getAbsolutePath();
            // 先判断图片是否已被压缩过
            if (!compressImgMap.containsKey(s)) {// 未被压缩
                // 压缩
                source = Tinify.fromFile(s);
                source.toFile(path);

                // 存储信息到配置文件
                imgFile = new File(s);// 新图片
                byteArray = getBytes(s);
                byteStr = MD5Util.byteArrayToHexString(byteArray);
                prop.setProperty(path, MD5Util.MD5Encode(byteStr));
                log.info("图片" + s + "压缩成功");
            } else {// 配置文件有该路径,判断对应的图片是否被压缩的图片
                String oldSign = compressImgMap.get(s).toString();
                imgFile = new File(s);// 新图片
                byteArray = getBytes(s);
                byteStr = MD5Util.byteArrayToHexString(byteArray);
                String newSign = MD5Util.MD5Encode(byteStr);
                if (oldSign.equals(newSign)) {
                    log.info("图片" + s + "已被压缩,无需重复压缩");
                } else {
                    // 压缩
                    source = Tinify.fromFile(s);
                    source.toFile(path);
                    log.info("图片" + s + "压缩成功");
                    // 存储信息到配置文件
                    prop.setProperty(path, MD5Util.MD5Encode(byteStr));
                }
            }

        } catch (Exception e) {
            log.info("图片" + s + "压缩失败," + e.getMessage());
            return s + "失败";
        }
        prop.store(oFile, null);
        oFile.close();
        return s + "成功";
    }

    public static byte[] getBytes(String filePath) {
        byte[] buffer = null;
        try {
            File file = new File(filePath);
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            fis.close();
            bos.close();
            buffer = bos.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffer;
    }
}

 

MD5工具类

public class MD5Util {
    private final static String[] hexDigits = { "0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };

    /**
     * 转换字节数组为16进制字串
     * 
     * @param b
     *            字节数组
     * @return 16进制字串
     */
    public static String byteArrayToHexString(byte[] b) {
        StringBuffer resultSb = new StringBuffer();
        for (int i = 0; i < b.length; i++) {
            resultSb.append(byteToHexString(b[i]));
        }
        return resultSb.toString();
    }

    /**
     * 转换byte到16进制
     * 
     * @param b
     * @return
     */
    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0) {
            n = 256 + n;
        }
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }

    /**
     * 编码
     * 
     * @param origin
     * @return
     */
    // MessageDigest 为 JDK 提供的加密类
    public static String MD5Encode(String origin) {
        String resultString = null;
        try {
            resultString = new String(origin);
            MessageDigest md = MessageDigest.getInstance("MD5");
            resultString = byteArrayToHexString(
                    md.digest(resultString.getBytes("UTF-8")));
        } catch (Exception ex) {
        }
        return resultString;
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值