更新時間:2022-08-24 來源:黑馬程序員 瀏覽量:
作者原創(chuàng):黑馬程序員講師——劉波 版權(quán)所有
引入
Markdown文檔的好處
相信很多朋友在開發(fā)和工作過程中都會使用MarkDown格式來編寫文檔,Markdown文檔的好處多多:
- 它基于純文本,方便修改和共享;
- 幾乎可以在所有的文本編輯器中編寫;
- 有眾多編程語言的實現(xiàn)和應(yīng)用的相關(guān)擴展;
- 在 GitHub 等網(wǎng)站中有很好的應(yīng)用;
- 很容易轉(zhuǎn)換為 HTML 文檔或其他格式;
- 適合用來編寫文檔、記錄筆記、撰寫文章。
而在眾多的MarkDown文檔的編輯器中,我們比較常用的一款工具是Typora,前幾年是免費的,最近1.0正式版以后開始要收費了。

Typora的優(yōu)勢
Typora容許隨時隨地開展無縫拼接瀏覽,從而可以在編輯的同時及時的看到效果。筆者現(xiàn)在寫這個文檔就是使用的這個工具。它有以下好處:
1. 在Win,Mac和Linux上能用
2. 它具備審校作用,能夠檢查拼讀和英語的語法
3. 全自動匹配Markdown標(biāo)記,比如括弧
4. 支持大概100種語言并支持英語的語法突顯
5. 豐富多彩的作用和鍵盤快捷鍵
6. 與內(nèi)聯(lián)公式和顯示信息公式適配
Typora的不足
工具可以做到圖文并茂的編寫文檔,所有插入的圖片默認放在當(dāng)前文檔的assets目錄下,也可以通過設(shè)置指定圖片保存的位置,使用起來很方便。

但不足的是,如果文檔進行了修改,圖片從文檔中刪除了,殘留在當(dāng)前目錄下的assets目錄下的圖片并不會一同刪除。隨著文檔不斷的更新和修改,這個目錄下的圖片文件會越留越多,有時多達幾十M。不但占用空間,而且毫無用處。
<img src="assets/image-20220721102804143.png" alt="image-20220721102804143" style="zoom:80%;" />
雖然我們可以手動點擊每張圖片查看具體是哪張圖片,再一張張手工去刪除,但圖片如果多的話,也是很繁瑣的事情,而且考驗人的耐心。
<img src="assets/image-20220721102924085.png" alt="image-20220721102924085" style="zoom:80%;" />
我們能不能自己寫個程序,分析整個Markdown文檔中的圖片地址,然后批量刪除呢?有了這個想法以后,我就自己花了一些時間做了一個,目前已經(jīng)使用了一年多了,沒有發(fā)現(xiàn)什么問題,特意寫出來分享給大家。
實現(xiàn)思路
思路
首先我們需要分析Markdown文檔的格式,它本質(zhì)上就是一個文本文件。大致實現(xiàn)思路如下:
1. 使用Java中的IO流API對文檔進行解析
2. 找到文檔中圖片的地址,使用正則表達式進行分析,將所有文檔中出現(xiàn)的圖片文件名保存成一個集合。
3. 再到assets文件夾下去查找所有的圖片文件名,也保存成一個集合。
4. 對比兩個文件名的集合,將在assets目錄下存在的文件,文檔中不存在的圖片文件全部找出來
5. 刪除所有不存在的圖片文件
源代碼
```java
package org.newboy.utils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author NewBoy
* @version 1.0
* @since 2020-12-04
* 刪除MarkDown目錄下多余的圖片文件
*/
public class MarkDownPictureCleaner {
public static void main(String[] args) {
System.out.println("=== MarkDown下冗余圖片清理工具(開發(fā)者:NewBoy 版本:1.0) ===");
Scanner scanner = new Scanner(System.in);
//MarkDown的文件名
String path = null;
try {
System.out.println("請輸入Markdown文件的路徑和文件名(可直接將md文件拖到命令窗口):");
path = scanner.nextLine();
} catch (Exception e) { // 用戶可能按下 Ctrl + C 終止程序
System.out.println("程序結(jié)束!");
scanner.close();
System.exit(0);
}
// 預(yù)檢查,判斷用戶輸入的文件是否存在
File file = null;
//圖片所在目錄
String picDir = null;
if (StringUtils.isNotBlank(path)) {
//如果用戶在DOS命令窗口拖入,前后有雙引號,去掉雙引號
path = path.trim().replace("\"", "");
//創(chuàng)建文件對象
file = new File(path);
if (!file.exists()) {
System.out.println("Markdown文件不存在!");
file = null;
}
else {
System.out.println("請輸入圖片目錄(默認為assets):");
//圖片所在目錄
picDir = scanner.nextLine();
//如果為空,空串,或者空格
if (StringUtils.isBlank(picDir)) {
picDir = "assets";
}
}
}
// 讀取 Markdown 文件的內(nèi)容
String content = null;
if (file != null) { // 如果用戶輸入的文件不存在,跳過此次操作
System.out.println("您輸入的路徑:" + file.getAbsolutePath());
try {
content = FileUtils.readFileToString(file, "UTF-8");
} catch (IOException e) {
System.out.println("文件讀取異常:" + e.getMessage());
content = null;
}
}
if (content != null) {
// 找出 Markdown 文件中所有圖片的引用
String regex = "(!\\[.*\\])(\\(.*\\))|(<img\\b.*?(?:\\>|\\/>))"; // 捕獲組,匹配類似于 "" 的字符串
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(content);
HashSet<String> picturesInMarkdown = new HashSet<>();
while (matcher.find()) {
String ref = matcher.group(0);
String picture = null;
int beginIndex = 0;
int endIndex = 0;
//如果是!開頭
if (ref.startsWith("!")) {
// 獲取圖片名稱
beginIndex = ref.lastIndexOf("/") + 1;
endIndex = ref.length() - 1;
} else if (ref.startsWith("<")) { //或者以<開頭的
beginIndex = ref.indexOf("/") + 1;
endIndex = ref.indexOf('"', beginIndex);
}
picture = ref.substring(beginIndex, endIndex);
//logger.info(picture);
// 保存圖片名稱
picturesInMarkdown.add(picture);
}
System.out.println("MarkDown中一共有:" + picturesInMarkdown.size() + "個圖片文件");
// 列出 Markdown 文件所在目錄中的圖片名稱
File directory = file.getParentFile();
String[] extensions = {"png", "jpg", "jpeg", "bmp"}; // 圖片擴展名
boolean recursive = true; // 不掃描子目錄
HashSet<String> picturesInDirectory = new HashSet<String>();
//獲取所有文件的集合
Collection<File> files = FileUtils.listFiles(directory, extensions, recursive);
System.out.println("圖片目錄下一共有:" + files.size() + "個圖片文件");
for (File picture : files) {
String name = picture.getName();
picturesInDirectory.add(name);
}
// 列出冗余圖片,并將其刪除
picturesInDirectory.removeAll(picturesInMarkdown);
int count = 0;
for (String picture : picturesInDirectory) {
String pic = directory.getAbsolutePath() + File.separator + picDir + File.separator + picture;
System.out.println("刪除圖片:" + pic);
FileUtils.deleteQuietly(new File(pic));
count++;
}
System.out.println("操作完成,共刪除了" + count + "個圖片文件!");
}
scanner.close();
System.exit(0);
}
}
```
使用說明
因為使用Java編寫,使用需要安裝Java虛擬機,為了方便用戶的使用,特意編寫了一個DOS下的命令行
``` @echo off java -jar markdown-picture-cleaner-1.0.jar pause ```
1. 運行的時候會出現(xiàn)一個窗口,需要輸入Markdown文件的路徑和文件名,這個比較麻煩,但可以將需要清理的文件直接拖到窗口中,則會自動填充文件路徑和文件名

2. 拖到窗口中會自動輸入路徑和文件名
<img src="assets/image-20220721105304355.png" alt="image-20220721105304355" style="zoom:80%;" />
3. 按下回車會讓你輸入圖片的目錄,默認是當(dāng)前目錄下的assets,如果圖片是在這個目錄下,直接按回車即可。

4. 最后顯示清理的結(jié)果

最后
以上是給各位讀者提供了一種思路,大家也可以使用其它語言進行編寫,比如可以直接運行在Windows下的VC或是VB,還有圖形界面,用戶體驗會更好一些。同時軟件本身只提供了基礎(chǔ)功能,作者提供了源代碼,懂Java的朋友可以在這個基礎(chǔ)上去進一步完善。