Typora图片批量迁移至指定位置(java)

Typora图片批量迁移至指定位置(java)

一、迁移图片时请备份图片源文件和md文本

  • 引用内容

  • https://blog.youkuaiyun.com/mekings13/article/details/135552433

二、处理结果图

1.单独目录处理

  • 在这里插入图片描述

2.多目录递归处理

  • 在这里插入图片描述

3.图片迁移前后文件比较(图片路径)

  • 在这里插入图片描述

三、缺陷提示

  • 提取图片使用的分隔符为 ![image-
  • ](
  • <img src
  • ="
  • 支持单行多图片的迁移
    例如 !'‘image-xxx 笔记xxxxx!’‘image-xxx xxxxx !’'image-xxx <'img src=“xxxxxx” />
  • 分割代码如下
  • 在这里插入图片描述

四、及时修改Typora图片保存策略

  • 在这里插入图片描述

  • 在这里插入图片描述

五、Java代码

package com.xqh.操作类.typora图片迁移;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.util.*;

public class TyporaImagesMoveSimple {

    public static void main(String[] args) {
        com.xqh.操作类.typora图片迁移.TyporaImagesMove typoraImagesMove = new com.xqh.操作类.typora图片迁移.TyporaImagesMove();
        typoraImagesMove.start();
        //TODO 测试方法 使用下面测试 请注释上一行代码
//        typoraImagesMove.test();
    }

    public void start() {
        String directPath = "";// typora md文件路径
        String copyPrefixPath = "";// 图片复制迁移目录

        // 创建Scanner对象并传入标准输入流(键盘)作为参数
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入需要处理的md文件目录路径:");
        // 读取用户输入的字符串
        String input = scanner.nextLine();
        this.fileExists(input);

        System.out.print("请输入图片迁移至目标的文件路径:");
        String tagPath = scanner.nextLine();

        System.out.print("请输入处理类型:0: 单个目录处理;1: 目录递归处理");
        String typeExecute = scanner.nextLine();
        scanner.close();

        directPath = input;
        copyPrefixPath = tagPath;

        this.createImageFile(copyPrefixPath);


        if("0".equals(typeExecute)){
            this.singleFile(directPath, copyPrefixPath);
        }else if ("1".equals(typeExecute)){
            this.recursionFile(directPath, copyPrefixPath);
        }else {
            System.out.println("请正确输入处理类型!");
        }
    }

    /**
     * 单个目录处理
     * @param directPath 目录路径
     * @param copyPrefixPath  图片复制迁移目录
     */
    public void singleFile(String directPath, String copyPrefixPath){
        File file = new File(directPath);
        if(!file.exists()){
            throw new RuntimeException("源文件目录为空");
        }
        String[] list = file.list();
        if(list.length == 0){
            throw new RuntimeException("空目录");
        }
        for(String fileName : list){
            // 只处理md文件
            if (!fileName.contains(".md")){
                continue;
            }
            this.executeFile(directPath, fileName, copyPrefixPath, null);
        }
    }


    /**
     * 递归目录处理
     * @param directPath 目录路径
     * @param copyPrefixPath 图片复制迁移目录
     */
    public void recursionFile(String directPath, String copyPrefixPath){
        File file = new File(directPath);
        ArrayList<String> allFileList = new ArrayList<>();
        this.getAllFileMap2(file, allFileList);

        for (String absPathFile : allFileList) {
            this.executeFile(null, null, copyPrefixPath, absPathFile);
        }
    }


    /**
     * 单文件处理
     * @param directPath 源文件目录
     * @param fileName 文件名
     * @param copyPrefixPath 图片复制迁移目录
     * @param absPathFile 源文件绝对路径 // 递归目录时使用此参数,单目录处理填写null,directPath、fileName填null
     */
    public void executeFile(String directPath, String fileName, String copyPrefixPath, String absPathFile){
        try{
            String filePath = "";
            if(StringUtils.isNotEmpty(absPathFile) && StringUtils.isEmpty(directPath)){
                filePath = absPathFile;
                int separatorIndex = absPathFile.lastIndexOf(File.separator) + 1;
                fileName = absPathFile.substring(separatorIndex, absPathFile.length());
            }else {
                filePath = directPath + File.separator + fileName;
            }

            List<String> lines = this.readFile(filePath);// 将该md文件内容读取出来存进List<String>中方便后续处理
            List<String> newLines = new LinkedList<>();// 建一个新的List<String>用于接受处理好的内容


            for (String line : lines) {// 开始对每一行内容进行处理

                // 图片md的格式是这样的:![image-20240111153157024](图片路径)
                if (StringUtils.isNotBlank(line) && line.contains("![image") ||
                        (StringUtils.isNotBlank(line) && line.contains("<img src="))) {// 判断此行是否存在图片

                    String newLine = line;
                    ArrayList<String> oldUrlImagesList = new ArrayList<>();// 需要替换的图片集
                    ArrayList<String> expiredImagesList = new ArrayList<>();// 过时图片/不存在的图片集

                    // ![image 默认图片格式
                    if(line.contains("![image")){
                        // 只分割typora格式的图片 ![image-
                        String[] split1 = line.split("!\\[image-");

                        for (String split2 : split1) {

                            int start = split2.indexOf("](");// 判断](图片格式是否存在
                            if(StringUtils.isEmpty(split2) || start == -1){
                                continue;
                            }
                            start = start + 2;
                            int end = split2.indexOf(")");
                            if(end == -1){
                                continue;
                            }
                            String imagesUrl = split2.substring(start, end);
                            // 不处理网络图片和本地file:///手写统一资源图片
                            if(imagesUrl.contains("https://") || imagesUrl.contains("http://") || imagesUrl.contains("file:///")){
                                continue;
                            }
                            if(this.existsImages(imagesUrl)){
                                oldUrlImagesList.add(imagesUrl);
                            }else{
                                expiredImagesList.add(imagesUrl);
                            }
                        }
                    }

                    // 调整过图片大小的处理
                    if(line.contains("<img src=")){
                        String[] split1 = line.split("<img src");
                        for (String split2 : split1) {
                            if(!split2.startsWith("=\"")){
                                continue;
                            }
                            String end = "\" ";
                            if(!split2.contains(end)){
                                continue;
                            }
                            int endIndex = split2.indexOf(end);
                            String imagesUrl = split2.substring(2, endIndex);
                            // 不处理网络图片和本地file:///手写统一资源图片
                            if(imagesUrl.contains("https://") || imagesUrl.contains("http://") || imagesUrl.contains("file:///")){
                                continue;
                            }
                            if(this.existsImages(imagesUrl)){
                                oldUrlImagesList.add(imagesUrl);
                            }else{
                                expiredImagesList.add(imagesUrl);
                            }
                        }
                    }

                    // 行图片文本替换 & 复制迁移图片
                    if(ObjectUtils.isNotEmpty(oldUrlImagesList)){
                        for (String imagesUrl : oldUrlImagesList) {
                            int separatorIndex = imagesUrl.lastIndexOf(File.separator) + 1;
                            String imagesName = imagesUrl.substring(separatorIndex, imagesUrl.length());
                            String newImagesUrl = copyPrefixPath + File.separator + imagesName;

                            newLine = newLine.replace(imagesUrl, newImagesUrl);
                        }
                        // 复制迁移图片路径
                        this.moveCopyImages(fileName, oldUrlImagesList, copyPrefixPath);
                    }
                    if(ObjectUtils.isNotEmpty(expiredImagesList)){
                        for (String imagesName : expiredImagesList) {
                            System.out.println("Untreated_images=> 文件:"+ fileName +" 处理异常,\n\t图片info: "+ imagesName +
                                    " \n\t异常信息:"+ " 图片过期、图片格式不正确、无法访问(想同位置无法访问) !");
                        }
                    }
                    // 更新行内容
                    line = newLine;
                }
                // 将内容存进新list
                newLines.add(line);
            }

            // 将处理好的md内容重新写进md文件中
            this.writeFile(newLines, filePath);
            System.out.println("Finish_file=> " + filePath + "--->" + "文件:"+ fileName +" 已处理成功");
        }catch (Exception e){
            System.out.println("文件:"+ fileName +" 处理异常,异常信息:"+ e.getMessage() + "");
        }
    }


    /**
     * 递归获取所有文件
     * @param subFile 子文件信息
     * @param allFileList ArrayList<String> allFileList 集合
     */
    public void getAllFileMap2(File subFile, ArrayList<String> allFileList){
        if (subFile.list().length == 0 ){
//            System.out.println("递归子目录为空");
            return;
        }

        for (File xFile : subFile.listFiles()) {
            String xName = xFile.getName();
            if (xFile.isFile() && xName.contains(".md")){
                allFileList.add(xFile.getAbsolutePath());
                continue;
            }
            // 递归循环文件
            if(xFile.isDirectory()){
                this.getAllFileMap2(xFile, allFileList);
            }
        }

    }

    /**
     * 读取文件行内容
     * @param filePath 路径
     * @return list lineList集合
     */
    public List<String> readFile(String filePath){
        List<String> lines = new LinkedList<>();
        try (BufferedReader reader = new BufferedReader(new FileReader(filePath)))
        {
            String lineStr;
            while ((lineStr = reader.readLine())!=null) {
                lines.add(lineStr);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return lines;
    }

    /**
     * 将修改的内容写回文件
     * @param lineList lineList
     * @param filePath filePath 文件绝对路径
     */
    public void writeFile(List<String> lineList, String filePath){
        try(BufferedWriter reader = new BufferedWriter(new FileWriter(filePath))){
            for (String line : lineList){
                reader.write(line);
                reader.newLine();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 判断目录是否存在
     * @param file 路径
     */
    public void fileExists(String file){
        File f = new File(file);
        if(!f.exists()){
            throw new RuntimeException("源文件目录为空");
        }
    }


    /**
     * 创建图片复制迁移目录
     * @param imagesPath 路径
     */
    public void createImageFile(String imagesPath){
        File imagesDirect = new File(imagesPath);
        try{
            if (!imagesDirect.exists()){
                imagesDirect.mkdirs();
            }else if (!imagesDirect.isDirectory()){
                imagesDirect.mkdirs();
            }
        }catch (Exception e){
            throw new RuntimeException("目标路径输入错误,或不磁盘不存在");
        }
    }

    /**
     * 图片复制方法
     * @param fileName 文件名
     * @param oldUrlImagesList 源图片路径集合
     * @param copyPrefixPath 图片复制迁移目标目录路径
     */
    public void moveCopyImages(String fileName, ArrayList<String> oldUrlImagesList, String copyPrefixPath){
        String copyImagePath = "";// 图片迁移最终位置
        try{
            for (String oldUrlImages : oldUrlImagesList) {
                File image = new File(oldUrlImages);
                copyImagePath = this.getImagesName(copyPrefixPath, oldUrlImages);
                File copyPath = new File(copyImagePath);
                // 将存在默认盘中的图片复制出来到 目标目录下
                FileUtils.copyFile(image, copyPath, true);
            }
        }catch (Exception e){
            System.out.println("Error_images=> 文件:"+ fileName +"处理异常,\n\t图片info: "+ copyImagePath +" \n\t异常信息:"+ e.getMessage() + "");
        }
    }

    /**
     * 获取迁移后图片的绝对路径
     * @param copyPrefixPath 迁移目录路径
     * @param imagesUrl 源图片路径
     * @return 新图片绝对路径
     */
    public String getImagesName(String copyPrefixPath, String imagesUrl){
        int separatorIndex = imagesUrl.lastIndexOf(File.separator) + 1;
        String imagesName = imagesUrl.substring(separatorIndex, imagesUrl.length());
        String newImagesUrl = copyPrefixPath + File.separator + imagesName;
        return newImagesUrl;
    }

    /**
     * 判断图片状态是否正常
     * @param imagesUrl imagesUrl
     * @return boolean
     */
    public boolean existsImages(String imagesUrl){
        File file = new File(imagesUrl);
        // 不处理网络图片
        if(imagesUrl.contains("https://") || imagesUrl.contains("http://") || imagesUrl.contains("file:///")){
            return false;
        }
        return file.exists();
    }


    /**
     * 测试入口
     */
    public void test(){
        String directPath = "D:" + File.separator + "xxx";// 源文件目录
//        String directPath = "D:" + File.separator + "vvv";
        String copyPrefixPath = "D:" + File.separator + "im";// 图片复制迁移目录

        this.createImageFile(copyPrefixPath);

        //TODO 使用下面其中一个方法,注释其另一个方法= =
//        this.singleFile(directPath, copyPrefixPath);// 单个目录处理
        this.recursionFile(directPath, copyPrefixPath);// 递归目录处理

    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值