批量替换MarkDown文档中指定的字符串

文章目录

  • 前言
  • 需要解决的问题
  • 解决方式和思路
    • 方式
    • 思路
  • 具体实现
    • 递归找到所有文件
    • 准备好源文件和目标文件
    • 将匹配的内容替换
  • 测试情况
  • 总结

前言

最近买了新电脑,各种配置要升级一下,几乎耗费了一个周末的时间,同时想将以前的博客文档导入过来,由于博客文档都是用Typora写的,其中图片也是存储在本地的。图片路径变化之后,文档中所有的图片都无法找到了,想着是不是可以通过工具解决这个事情

需要解决的问题

文档迁移之后,原有的文档中的图片都变成了这样
在这里插入图片描述

由于指定的文件路径找不到了,才会变成这样子。因此想到了,是不是可以通过文档替换的方式解决

解决方式和思路

方式

打开Typora编辑器,通过查找替换功能将图片路径替换成新的路径之后,图片可正常显示

在这里插入图片描述

那么问题来了,一个个手动替换?这也太原始了,于是就在这个背景下,写了一个批量替换文档中指定内容的代码,后来测试成功了,这里记录一下。

思路

第一步:递归找到所有文件;第二步:准备好源文件和目标文件;第三步:将匹配的内容替换,并将文件输出到指定的新文件

具体实现

在上面的思路上有着如下实现

递归找到所有文件

直接上代码,这个对我们来说应该不难,只是加入了一个是否是markdown文件的判断

private static Set<String> markDownFileSuffix = new HashSet<>();static {//只处理md文件markDownFileSuffix.add("md");
}/*** 递归读取文件夹下的所有文件** @param path*/
public static void readFileInDir(String path, List<File> fileList) {File f = new File(path);//得到文件下的所有文件File[] files = f.listFiles();for (File file : files) {if (file.isDirectory()) {readFileInDir(file.getAbsolutePath(), fileList);} else {if (isMarkDownFile(file.getName())) {fileList.add(file);}}}
}/*** 判断是否是markdown文档** @param fileName* @return*/
public static boolean isMarkDownFile(String fileName) {boolean result = false;String suffix = fileName.substring(fileName.lastIndexOf('.') + 1);if (markDownFileSuffix.contains(suffix)) {result = true;}return result;
}

准备好源文件和目标文件

由于有一个强迫症,并且为了避免之前的分类的文件夹乱掉,这里要求源文件是存在那个文件夹下,新的文件也一样存在那个分类的文件夹下,只是根目录不同而已。

因此在正式处理文件之前,先准备好目标文件才是硬道理

/*** 根据原文件路径,创建目标文件* @param sourceFile 源文件* @param targetFileDir 目标文件根路径* @return 创建好的目标文件*/
public static File createTargetFile(File sourceFile,String targetFileDir){//获取源文件绝对路径String sourceFileAbsoluteName = sourceFile.getAbsolutePath();//替换根路径,这里为了简单直接硬编码了,第一个参数可以有外部传递进来String afterDealFileName = sourceFileAbsoluteName.replace("F:\\blog_doc", targetFileDir);//截取出文件夹路径和文件名int splitIndex = afterDealFileName.lastIndexOf("\\");//文件夹路径String dirPath = afterDealFileName.substring(0,splitIndex+1);//文件名String createFileName = afterDealFileName.substring(splitIndex+1);log.info("准备创建的目标文件名为:{},存在于:{}文件夹",createFileName,dirPath);//先递归创建文件夹File dirFile = new File(dirPath);if(!dirFile.exists()){dirFile.mkdirs();log.info("文件夹:{}创建完成",dirPath);}//创建目标文件File targetFile = new File(dirPath,createFileName);if(!targetFile.exists()){try {targetFile.createNewFile();} catch (IOException e) {log.error("文件:{}创建异常:{}",targetFile.getAbsolutePath(),e);return null;}log.info("文件:{}创建完成",targetFile.getAbsolutePath());}//返回已经创建的文件return targetFile;
}

将匹配的内容替换

将源文档中的指定内容替换,并输出到新的文档中

/*** 开始替换文件中的内容* @param sourceFile 源文件* @param targetRegex 需要匹配的正则表达式* @param toReplaceStr 需要替换成的字符串*/
public static void replaceImgPath(File sourceFile, String targetRegex, String toReplaceStr) {String regex = targetRegex;String targetFileDir = "F:\\博客文档_新";//目标文件夹,处理之后的文件,都会写入到这个文件夹中,并且保证按照原有文件路径分类BufferedReader reader = null;BufferedWriter writer = null;log.info("开始处理文件:{},最终文件会存在目录:{}中",sourceFile.getAbsoluteFile(),targetFileDir);String fileName = sourceFile.getAbsoluteFile() + "/" + sourceFile.getName();try {//构造源文件读取器reader = new BufferedReader(new InputStreamReader(new FileInputStream(sourceFile)));//创建目标文件File targetFile = createTargetFile(sourceFile,targetFileDir);if(null == targetFile){log.info("文件:{},目标文件创建失败,请手动操作",sourceFile.getAbsolutePath());return;}//构造目标文件写入器writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(targetFile)));String tempStr = "";String regStr = regex;//有点多余,可以删除Pattern pattern = Pattern.compile(regStr);while ((tempStr = reader.readLine()) != null) {tempStr += "\n"; //加上换行,避免格式错乱Matcher matcher = pattern.matcher(tempStr);if (matcher.find()) {//如果匹配上,进行替换//按照指定正则替换tempStr = tempStr.replaceAll(regex, toReplaceStr);log.info("文件:{},替换后的字符串为:{}",sourceFile.getAbsoluteFile(), tempStr);count++;//统计匹配的个数}writer.write(tempStr);}writer.flush();} catch (Exception e) {//记录异常log.error("文件:{},字符替换异常,异常信息为:{},请手动操作", fileName,e);return;} finally {//关闭流try {reader.close();} catch (IOException e) {log.error("文件:{},流关闭异常", fileName);}try {writer.close();} catch (IOException e) {log.error("文件:{},流关闭异常", fileName);}}
}

测试情况

完整代码

package com.learn.sample;import lombok.extern.slf4j.Slf4j;import java.io.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;/*** autor:liman* createtime:2021-10-31* comment: 读取已经编写的markdown文档,并对指定字符进行正则替换*/
@Slf4j
public class ReplaceDocFileTools {private static Set<String> markDownFileSuffix = new HashSet<>();private static Integer count = 0;static {//只处理md文件markDownFileSuffix.add("md");}public static void main(String[] args) throws IOException {long startTime = System.currentTimeMillis();String path = "F:\\blog_doc\\博客文档";//1.读取文件夹下的所有视频文件List<File> fileList = new ArrayList<>();readFileInDir(path, fileList);List<String> fileNameList = fileList.stream().map(File::getName).collect(Collectors.toList());log.info("得到的文件列表为:");fileNameList.stream().forEach(t -> System.out.println(t));log.info("待转换的文件个数为:{}",fileNameList.size());String toRegexStr = "E{1}\\:\\\\blogPic\\b";String toReplaceStr = "F:\\\\blog_doc\\\\blogPic";fileList.stream().forEach(t -> replaceImgPath(t, toRegexStr, toReplaceStr));long endTime = System.currentTimeMillis();long costTime = endTime - startTime;log.info("批量文件字符串替换完成,原始文件个数:{},总共替换字符串:{}个,总共耗时:{}ms",fileNameList.size(),count,costTime);}/*** 递归读取文件夹下的所有文件** @param path*/public static void readFileInDir(String path, List<File> fileList) {File f = new File(path);//得到文件下的所有文件File[] files = f.listFiles();for (File file : files) {if (file.isDirectory()) {readFileInDir(file.getAbsolutePath(), fileList);} else {if (isMarkDownFile(file.getName())) {fileList.add(file);}}}}/*** 判断是否是markdown文档** @param fileName* @return*/public static boolean isMarkDownFile(String fileName) {boolean result = false;String suffix = fileName.substring(fileName.lastIndexOf('.') + 1);if (markDownFileSuffix.contains(suffix)) {result = true;}return result;}/*** 开始替换文件中的内容* @param sourceFile 源文件* @param targetRegex 需要匹配的正则表达式* @param toReplaceStr 需要替换成的字符串*/public static void replaceImgPath(File sourceFile, String targetRegex, String toReplaceStr) {String regex = targetRegex;String targetFileDir = "F:\\博客文档_新";//目标文件夹,处理之后的文件,都会写入到这个文件夹中,并且保证按照原有文件路径分类BufferedReader reader = null;BufferedWriter writer = null;log.info("开始处理文件:{},最终文件会存在目录:{}中",sourceFile.getAbsoluteFile(),targetFileDir);String fileName = sourceFile.getAbsoluteFile() + "/" + sourceFile.getName();try {//构造源文件读取器reader = new BufferedReader(new InputStreamReader(new FileInputStream(sourceFile)));//创建目标文件File targetFile = createTargetFile(sourceFile,targetFileDir);if(null == targetFile){log.info("文件:{},目标文件创建失败,请手动操作",sourceFile.getAbsolutePath());return;}//构造目标文件写入器writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(targetFile)));String tempStr = "";String regStr = regex;Pattern pattern = Pattern.compile(regStr);while ((tempStr = reader.readLine()) != null) {tempStr += "\n"; //加上换行,避免格式错乱Matcher matcher = pattern.matcher(tempStr);if (matcher.find()) {//如果匹配上,进行替换//按照指定正则替换tempStr = tempStr.replaceAll(regex, toReplaceStr);log.info("文件:{},替换后的字符串为:{}",sourceFile.getAbsoluteFile(), tempStr);count++;}writer.write(tempStr);}writer.flush();} catch (Exception e) {//记录异常log.error("文件:{},字符替换异常,异常信息为:{},请手动操作", fileName,e);return;} finally {//关闭流try {reader.close();} catch (IOException e) {log.error("文件:{},流关闭异常", fileName);}try {writer.close();} catch (IOException e) {log.error("文件:{},流关闭异常", fileName);}}}/*** 根据原文件路径,创建目标文件* @param sourceFile 源文件* @param targetFileDir 目标文件根路径* @return*/public static File createTargetFile(File sourceFile,String targetFileDir){//获取源文件绝对路径String sourceFileAbsoluteName = sourceFile.getAbsolutePath();String afterDealFileName = sourceFileAbsoluteName.replace("F:\\blog_doc", targetFileDir);//截取出文件夹路径和文件名int splitIndex = afterDealFileName.lastIndexOf("\\");//文件夹路径String dirPath = afterDealFileName.substring(0,splitIndex+1);//文件名String createFileName = afterDealFileName.substring(splitIndex+1);log.info("准备创建的目标文件名为:{},存在于:{}文件夹",createFileName,dirPath);//先递归创建文件夹File dirFile = new File(dirPath);if(!dirFile.exists()){dirFile.mkdirs();log.info("文件夹:{}创建完成",dirPath);}//创建目标文件File targetFile = new File(dirPath,createFileName);if(!targetFile.exists()){try {targetFile.createNewFile();} catch (IOException e) {log.error("文件:{}创建异常:{}",targetFile.getAbsolutePath(),e);return null;}log.info("文件:{}创建完成",targetFile.getAbsolutePath());}//返回已经创建的文件return targetFile;}
}

完整代码已贴出,运行情况如下所示

在这里插入图片描述

153个文档,替换1049处,耗时506毫秒

总结

一个简单的markdown文本替换工具


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部