更新時間: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的不足
工具可以做到圖文并茂的編寫文檔,所有插入的圖片默認(rèn)放在當(dāng)前文檔的assets目錄下,也可以通過設(shè)置指定圖片保存的位置,使用起來很方便。
但不足的是,如果文檔進(jìn)行了修改,圖片從文檔中刪除了,殘留在當(dāng)前目錄下的assets目錄下的圖片并不會一同刪除。隨著文檔不斷的更新和修改,這個目錄下的圖片文件會越留越多,有時多達(dá)幾十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對文檔進(jìn)行解析
2. 找到文檔中圖片的地址,使用正則表達(dá)式進(jìn)行分析,將所有文檔中出現(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("請輸入圖片目錄(默認(rèn)為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. 按下回車會讓你輸入圖片的目錄,默認(rèn)是當(dāng)前目錄下的assets,如果圖片是在這個目錄下,直接按回車即可。
4. 最后顯示清理的結(jié)果
最后
以上是給各位讀者提供了一種思路,大家也可以使用其它語言進(jìn)行編寫,比如可以直接運行在Windows下的VC或是VB,還有圖形界面,用戶體驗會更好一些。同時軟件本身只提供了基礎(chǔ)功能,作者提供了源代碼,懂Java的朋友可以在這個基礎(chǔ)上去進(jìn)一步完善。